spring中jdbc声明式事务和spring基于xmlschema、annotation的声明式事务(事务3)

JDBC声明事务管理

Spring的声明式事务管理依赖他的aop框架来完成。施工声明式事务管理的好处是事务管理不能侵入我们开发的组件,Dao对象不会意识到正在事务管理之中。

 

例子:

#

packagecom.springframework.sample.jdbc.dao;

 

import java.util.List;

 

importcom.springframework.sample.jdbc.pojo.Banzu;

 

public interface DaoInterface {

   publicvoid saveBanzu(Banzu banzu);

   publicList<Banzu> selectBanzu(String sql);

}

#

package com.springframework.sample.jdbc.dao;

 

import java.util.List;

 

import javax.sql.DataSource;

 

import org.springframework.jdbc.core.JdbcTemplate;

 

import com.springframework.sample.jdbc.pojo.Banzu;

import com.springframework.sample.jdbc.pojo.BanzuRowMapper;

 

public classDaoServiceImpl2 implements DaoInterface {

   private JdbcTemplate jdbcTemplate;

 

   public voidsetDataSource(DataSource dataSource) {

      this.jdbcTemplate = new JdbcTemplate(dataSource);

   }

 

   @Override

   public void saveBanzu(Banzu banzu) {

      // TODO Auto-generated method stub

      jdbcTemplate.update("insert intobanzu(BANZU_NAME,FUZEREN,BANZUCHENGYUAN) values(?,?,?)", newObject[]{banzu.getBanZu(),banzu.getFuZeRen(),banzu.getChengYuan()});

   }

 

   @Override

   public List<Banzu>selectBanzu(String sql){

      // TODO Auto-generated method stub

      List<Banzu>list  = jdbcTemplate.query(sql,newBanzuRowMapper());

      return list;

   }

 

}

#

package com.springframework.sample.jdbc.pojo;

 

public classBanzu {

   private String banZu;

   private String fuZeRen;

   private String chengYuan;

   public Banzu(){}

   public Banzu(String banZu,String fuZeRen,String chengYuan){

      this.banZu = banZu;

      this.fuZeRen = fuZeRen;

      this.chengYuan = chengYuan;

   }

   //set get

}

#

package com.springframework.sample.jdbc.pojo;

import java.sql.ResultSet;

import java.sql.SQLException;

importorg.springframework.jdbc.core.RowMapper;

 

public class BanzuRowMapperimplements RowMapper<Banzu> {

 

   @Override

   publicBanzu mapRow(ResultSet rs, int rowNum) throws SQLException {

      //TODO Auto-generated method stub

      Banzubanzu = newBanzu(rs.getString("BANZU_NAME"),rs.getString("FUZEREN"),rs.getString("BANZUCHENGYUAN"));

      returnbanzu;

   }

 

}

 

#test

public  static void main(String []args){

      ApplicationContextcontext= newClassPathXmlApplicationContext("spring-config.xml");

      Banzubanzu= newBanzu();

      banzu.setBanZu("ban3301");

      banzu.setChengYuan("du331,zhao332,long333");

      banzu.setFuZeRen("dudu333");

     

      DaoInterfaceserv=(DaoInterface) context.getBean("userDAOProxy");

      serv.saveBanzu(banzu);;

      List<Banzu>list= serv.selectBanzu("select * from banzu");

      for(int i=0;i<list.size();i++){

         Banzutemp_banzu= list.get(i);

         System.out.println("banzu name:"+temp_banzu.getBanZu()+" ,fuzeren:"+temp_banzu.getFuZeRen()+" ,chengyuan:"+temp_banzu.getChengYuan());

        

      }

   }

#

<?xml version="1.0"encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop" 

    xmlns:tx="http://www.springframework.org/schema/tx" 

    xmlns:context="http://www.springframework.org/schema/context"  

    xsi:schemaLocation=

        http://www.springframework.org/schema/context  

        http://www.springframework.org/schema/context/spring-context-3.0.xsd   

    http://www.springframework.org/schema/beans  

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

    http://www.springframework.org/schema/tx  

    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 

    http://www.springframework.org/schema/aop  

    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 

    

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

    

      <property name="driverClassName"  value ="oracle.jdbc.driver.OracleDriver"/>

      <property name="url"value ="jdbc:oracle:thin:@localhost:1521:orcl"/>

      <property name= "username"value = "scott" />

       <property name= "password"value = "adu636"/>

    </bean>

  

     <bean id= "jdbcTemplate2" class ="com.springframework.sample.jdbc.dao.DaoServiceImpl2">

      <property name="dataSource"ref = "dataSource"/>

    </bean>

   <bean id="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager">

      <property name = "dataSource" ref = "dataSource" />

   </bean>

   <bean id="userDAOProxy" class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

      <property name="proxyInterfaces">

         <list>

            <value>com.springframework.sample.jdbc.dao.DaoInterface</value>

         </list>

      </property>

      <property name="target" ref="jdbcTemplate2"/>

      <property name="transactionManager" ref ="transactionManager"/>

      <property name="transactionAttributes">

         <props>

            <prop key ="save*" >PROPAGATION_REQUIRED</prop>

         </props>

      </property>

   </bean>

    </beans>

 

TransactionPRoxyFactoryBean需要一个transactionManager,由于这里使用的DataSourceTransactionManager,TransactionProxyFactoryBean是一个代理对象,target属性指明被代理的对象也就是idjdbcTemplate2的类,事务管理会自动的介入指定的方法前后,transactionAttributes属性指定”save*”表示指定的方法名称已save开头的都要纳入事务管理中,如果发生错误,则所有先前的操作自动回撤,否则正常提交。

save*等方法上指定了PROPAGATION_REQUIRED,表示在目前的事务中执行操作,如果事务不存在,就新建一个。这个常数在之前的TransactionDefinition中已经介绍过了。

这里也可以加入多个中间用逗号分开,如
PROPAGATION_REQUIRED,readOnly,-MyCheckedException

MyCheckedException前面加入了-号,表示发生指定异常时撤销操作,如果前面是+号,表示发生异常时立即提交。

由于jdbcTemplate2usersDAOProxy代理了,所以要做的是取得userDAOProxy

 

 

我们可以通过设置不同的TransactionInterceptor来得到更多的管理细节。

<?xml version="1.0"encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop" 

    xmlns:tx="http://www.springframework.org/schema/tx" 

    xmlns:context="http://www.springframework.org/schema/context"  

    xsi:schemaLocation=

        http://www.springframework.org/schema/context  

        http://www.springframework.org/schema/context/spring-context-3.0.xsd   

     http://www.springframework.org/schema/beans  

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

    http://www.springframework.org/schema/tx  

    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 

     http://www.springframework.org/schema/aop  

    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 

    

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

    

      <property name="driverClassName"  value ="oracle.jdbc.driver.OracleDriver"/>

      <property name="url"value ="jdbc:oracle:thin:@localhost:1521:orcl"/>

      <property name= "username"value = "scott" />

      <property name= "password"value = "adu636"/>

    </bean>

    

    <bean id= "jdbcTemplate" class ="com.springframework.sample.jdbc.dao.DaoServiceImpl">

      <property name="dataSource"ref = "dataSource"/>

    </bean>

     <bean id= "jdbcTemplate2" class ="com.springframework.sample.jdbc.dao.DaoServiceImpl2">

      <property name="dataSource"ref = "dataSource"/>

    </bean>

   

    <bean id="service1" class="com.springframework.sample.jdbc.service.ServiceSample1">

       <property name="daoIntBanzu"ref ="jdbcTemplate" />

   </bean>

    <bean id="service2"class="com.springframework.sample.jdbc.service.ServiceSample2">

       <property name="daoIntBanzu"ref ="jdbcTemplate2" />

   </bean>

   <bean id="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager">

      <property name = "dataSource" ref = "dataSource" />

   </bean>

   <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">

      <property name ="transactionManager" ref ="transactionManager"/>

      <property name ="transactionAttributeSource" value="com.springframework.sample.jdbc.dao.DaoInterface.select*=PROPAGATION_REQUIRED"/>

   </bean>

   <bean id="userDAOProxy" class ="org.springframework.aop.framework.ProxyFactoryBean">

      <property name="proxyInterfaces">

         <list>

            <value>com.springframework.sample.jdbc.dao.DaoInterface</value>

         </list>

      </property>

      <property name="target" ref="jdbcTemplate2"/>

  

      <property name ="interceptorNames" >

         <list>

            <value>transactionInterceptor</value>

         </list>

      </property>

   </bean>

    </beans>

这样也就是将sql操作和事务完全分开了,需要的时候只需要设置一下配置文件,不需要的时候可以直接修改配置文件,耦合性大大降低。

一个dataSource,一个DAOImpl,(JDBCTemplate

这里首先需要一个transactionManager(相当于advice);然后利用一个TransactionInterceptor拦截器(advisor),加入相应的pointcut,并且注入事务;最后是有proxyfactorybeanproxyInterface,target,interceptorNames等设置代理,之后只需要通过该代理即可获得被代理的对象。

 

5.3.5TransactionAttributeSourceTransactionAttribute

transactionProxyFactoryBean上有setTransactionAttributeSource与方法setTransactionAttribute()方法,他们是用来设置事务属性。

Methodkeytransactionattribute的相对应。

<property name="transactionAttributes">

         <props>

            <prop key ="save*" >PROPAGATION_REQUIRED</prop>

            <prop key ="select*" >PROPAGATION_REQUIRED</prop>

         </props>

      </property>

可以根据传递给它的method的实例,与class实例,决定返回一个transactionattribute,这里有一个实现org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource,它对于每一个方法指定都会应用事务,transactionattribute实例的默认传播行为时PROPAGATION_REQUIRED,隔离层级为ISOLATION_DEFAULT,为默认底层数据库的隔离层级。

 

 

这里如:

<bean id=”transactionAttributeSource”class =”org.springframework.transaction.interceptor.MatchhAlwaysTransactionAttributeSource”/>

<bean id=”userDAOProxy” class =”org.springframework.transaction.interceptor.TransactionProxyFactoryBean”>

   <propertyname =”proxyInterfaces”>

      <list>

         <value>com.springframework.sample.DaoInterface</value>

</list>

   </property>

   <propertyname=”target” ref =”userDAO”/>

   <propertyname=”transactionManager” ref =”transactionManager”/>

   <propertyname =”transactionAttributeSource” ref =”transactionAttributeSource”/>

</bean>

 

也可以使用org.springframework.transaction.interceptor.DefaultTransactionAttribute,并设置自己的策略,之后设置给TransactionAttributeSource

如:

<bean id=”myTransactionAttribute”class =”org.springframework.transaction.interceptor.DefaultTransactionAttribute”>

   <propertyname=”propagationBehaviorName” value =”PROPAGATION_REQUIRED_NEW”/>

   <propertyname =”isolationLevelName” value=”ISOLATION_REPEATABLE_READ”/>

</bean>

其他设置如上

 

也可以使用如下来指定某些方法要应用事务,以及应用事务的策略。如org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource

<bean id=”transactionAttributeSource”class =”org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource”>

   <propertyname =”properties”>

      <props>

         <propkey= “save*”>PROPAGATION_REQUIRED_NEW</prop>

</props>

   </property>

</bean>

 

K这里只要是save开头的方法都会使用事务。

 

在指定事务策略时,指定的格式如下:

传播行为,隔离层级,只读,+异常,-异常

传播行为必须要设置,其他的可以省略。

 

简单的设置是仅设置TransactionProxyFactoryBean,并在他的transactionAttributes中直接设置应用事务的方法及事务策略。

如:

<bean id="userDAOProxy2" class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

      <property name="proxyInterfaces">

         <list>

            <value>com.springframework.sample.jdbc.dao.DaoInterface</value>

         </list>

      </property>

      <property name="target" ref="jdbcTemplate2"/>

      <property name ="transactionManager" ref ="transactionManager"/>

      <property name="transactionAttributes">

         <props>

            <prop key="save*">PROPAGATION_REQUIRED</prop>

            <prop key ="select*" >PROPAGATION_REQUIRED</prop>

         </props>

      </property>

     

   </bean>

也可以直接指定TransactionInterceptor,以便获得更多的控制。

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">

      <property name ="transactionManager" ref ="transactionManager"/>

      <property name ="transactionAttributeSource" value="com.springframework.sample.jdbc.dao.DaoInterface.select*=PROPAGATION_REQUIRED"/>

   </bean>

   <bean id="userDAOProxy" class ="org.springframework.aop.framework.ProxyFactoryBean">

      <property name="proxyInterfaces">

         <list>

            <value>com.springframework.sample.jdbc.dao.DaoInterface</value>

         </list>

      </property>

      <property name="target" ref="jdbcTemplate2"/>

  

      <property name ="interceptorNames" >

         <list>

            <value>transactionInterceptor</value>

         </list>

      </property>

   </bean>

究竟选择哪种方式实现事务,可以根据实际情况选择。

 

5.3.6 spring2.0声明式事务管理

声明式事务管理可以分为基于xmlschema的和基于annotation注解形式的两种。

(一)基于xmlschema的方式

(1)  基于xmlschema的声明式事务管理,可以依赖于<aop>,<tx>的标签配置,这里要加入其相应的名称空间声明。

  Dhi

<?xml version="1.0"encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop" 

    xmlns:tx="http://www.springframework.org/schema/tx" 

    xmlns:context="http://www.springframework.org/schema/context"  

    xsi:schemaLocation=

        http://www.springframework.org/schema/context  

         http://www.springframework.org/schema/context/spring-context-3.0.xsd   

    http://www.springframework.org/schema/beans  

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

     http://www.springframework.org/schema/tx  

    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 

    http://www.springframework.org/schema/aop  

     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

….

</bean>

加粗的部分需要注意,这里涉及到相应的内容aop,tx的名称空间声明。

 

对于事务是系统层面的服务,也就是一个Aspect,具体来说就是一个advice(一个服务),可以使用<tx:advice>标签来提供这个服务,他需要设置一个transactionManager,并在当中使用<tx:attribute>设置事务属性,之后由<aop>标签将该advice和数据库操作DAO对象cross-cutting

具体的配置如下:

<?xml version="1.0"encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop" 

    xmlns:tx="http://www.springframework.org/schema/tx" 

    xmlns:context="http://www.springframework.org/schema/context"  

    xsi:schemaLocation=

        http://www.springframework.org/schema/context  

        http://www.springframework.org/schema/context/spring-context-3.0.xsd   

     http://www.springframework.org/schema/beans  

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

    http://www.springframework.org/schema/tx  

    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 

     http://www.springframework.org/schema/aop  

    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 

    

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

    

      <property name="driverClassName"  value ="oracle.jdbc.driver.OracleDriver"/>

      <property name="url"value ="jdbc:oracle:thin:@localhost:1521:orcl"/>

      <property name= "username"value = "scott" />

      <property name= "password"value = "adu636"/>

    </bean>

    

  

     <bean id= "jdbcTemplate2" class ="com.springframework.sample.jdbc.dao.DaoServiceImpl2">

      <property name="dataSource"ref = "dataSource"/>

    </bean>

   

   

    <bean id="service2"class="com.springframework.sample.jdbc.service.ServiceSample2">

       <property name="daoIntBanzu"ref ="jdbcTemplate2" />

   </bean>

   <bean id="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager">

      <property name = "dataSource" ref = "dataSource" />

   </bean>

   <tx:advice  id="txAdvice"transaction-manager="transactionManager">

      <tx:attributes>

         <tx:method name="save*" propagation="REQUIRED"/>

         <tx:method name ="select*" read-only="true"/>

      </tx:attributes>

   </tx:advice>

   <aop:config>

      <aop:pointcut id="userDAOPointcut" expression="execution(*com.springframework.sample.jdbc.dao.DaoInterface.*(..))" />

      <aop:advisor advice-ref="txAdvice"  pointcut-ref="userDAOPointcut"/>

   </aop:config>

     </beans>

这里配置了一个数据源DataSource,两个DAO,(jdbcTemplate),两个service,一个transactionManager,另外是一个<tx:advice>设置相应的advice,这里是设置的transactionmanager,最后是设置了一个<aop:config><aop:pointcut><aop:advisor>设置拦截的expressionpointcut里面设置),拦截后由advisor执行交由那个advice处理,也就是<tx:advice>的定义。

这里需要还需要aspectJweaver.jar需要会报错,关于pointcut的错误。

这里只需要如下操作即可获得相应的数据库操作和相应的事务处理

ApplicationContext context = newClassPathXmlApplicationContext("spring-config2.xml");

     

      ServiceSample2serv=(ServiceSample2) context.getBean("service2");

     

      List<Banzu>list= serv.getBanzu("select * from banzu");

      for(int i=0;i<list.size();i++){

         Banzutemp_banzu= list.get(i);

         System.out.println("banzu name:"+temp_banzu.getBanZu()+" ,fuzeren:"+temp_banzu.getFuZeRen()+" ,chengyuan:"+temp_banzu.getChengYuan());

    }

 

在<tx:advice>中属性设置,对于传播行为、隔离等级、只读、超时、异常时撤销会提交、都有对应的propagation/isolation/timeout/read-only/rollback-for/no-rollback-for等属性,如不设置,propagation默认REQUIRED,isolation默认是DEFAULT,timeout属性默认是-1(单位秒),read-only默认是false。

 

(二)基于注解annotation的方式

1方法是使用@Transactional来标示,例如可以直接改写

 

#DAO:

package com.springframework.sample.jdbc.dao;

 

import java.util.List;

 

import javax.sql.DataSource;

 

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.transaction.annotation.Transactional;

 

import com.springframework.sample.jdbc.pojo.Banzu;

import com.springframework.sample.jdbc.pojo.BanzuRowMapper;

 

public classDaoServiceImpl3 implements DaoInterface {

   private JdbcTemplate jdbcTemplate;

 

   public voidsetDataSource(DataSource dataSource) {

      this.jdbcTemplate = new JdbcTemplate(dataSource);

   }

   @Transactional(propagation=Propagation.REQUIRED)

   @Override

   public void saveBanzu(Banzu banzu) {

      // TODO Auto-generated method stub

      jdbcTemplate.update("insert intobanzu(BANZU_NAME,FUZEREN,BANZUCHENGYUAN) values(?,?,?)", newObject[]{banzu.getBanZu(),banzu.getFuZeRen(),banzu.getChengYuan()});

   }

   @Transactional(readOnly=true)

   @Override

   public List<Banzu> selectBanzu(String sql) {

      // TODO Auto-generated method stub

      List<Banzu>list  = jdbcTemplate.query(sql, new BanzuRowMapper());

      return list;

   }

 

}

#spring-config.xml

<?xml version="1.0"encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop" 

    xmlns:tx="http://www.springframework.org/schema/tx" 

    xmlns:context="http://www.springframework.org/schema/context"  

    xsi:schemaLocation=

        http://www.springframework.org/schema/context  

        http://www.springframework.org/schema/context/spring-context-3.0.xsd   

    http://www.springframework.org/schema/beans  

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

    http://www.springframework.org/schema/tx  

    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 

    http://www.springframework.org/schema/aop  

    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 

    

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

    

      <property name="driverClassName"  value ="oracle.jdbc.driver.OracleDriver"/>

      <property name="url"value ="jdbc:oracle:thin:@localhost:1521:orcl"/>

      <property name= "username"value = "scott" />

      <property name= "password"value = "adu636"/>

    </bean>

     <bean id= "jdbcTemplate3" class ="com.springframework.sample.jdbc.dao.DaoServiceImpl3">

      <property name="dataSource"ref = "dataSource"/>

    </bean>

  

    <bean id="service2"class="com.springframework.sample.jdbc.service.ServiceSample2">

       <property name="daoIntBanzu"ref ="jdbcTemplate3" />

   </bean>

   <bean id="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager">

      <property name ="dataSource" ref ="dataSource"/>

   </bean>

      <tx:annotation-driven  transaction-manager="transactionManager"/>

    </beans>

测试的时候可以直接获得service2,然后进行相应业务处理。

@Transactional(isolation=Isolation.DEFAULT)

 

@Transactionl(timeout=-1)

具体可以参考设置 TransactionDefinition 中定义)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值