spring+mybatis两种事务控制编写

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lj_dreamone/article/details/79614521

一.声明式事务管理
1.spring主配置文件头部添加以下代码
xmlns:aop=“http://www.springframework.org/schema/aop
xmlns:tx=“http://www.springframework.org/schema/tx
xsi:schemaLocation下添加如下代码:
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
2.配置事务管理器

<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">       
          <property name="dataSource" ref="dataSource"></property>  
</bean>

3.配置需要加入事务的规则

 <tx:advice id="iccardTxAdvice" transaction-manager="transactionManager">  
        <tx:attributes>  
          <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException"/>  
          <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />  
          <tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />  
          <tx:method name="create*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />  
          <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />  
            
          <tx:method name="find*" propagation="SUPPORTS" />  
          <tx:method name="get*" propagation="SUPPORTS" />  
          <tx:method name="select*" propagation="SUPPORTS" />  
          <tx:method name="query*" propagation="SUPPORTS" />  
        </tx:attributes>  
    </tx:advice>  
      
    <!-- 把事务控制在service层 -->  
    <aop:config>      
        <aop:pointcut id="iccardTerm" expression="execution(public * com.ucmed.hunst.service.*.*(..))" />  
        <aop:advisor pointcut-ref="iccardTerm" advice-ref="iccardTxAdvice" />  
    </aop:config> 

二.注解式事务管理
1.

<!-- 定义事务管理器 -->    
<bean id="transactionManager"    
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">    
    <property name="dataSource" ref="dataSource" />    
</bean>    
<!--使用注释事务 -->    
<tx:annotation-driven  transaction-manager="transactionManager" />  

2.在需要加入事务的方法或者类上添加@Transactional

事物配置中有哪些属性可以配置

(1)、事务的传播性:@Transactional(propagation=Propagation.REQUIRED)

  如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)

(2)、事务的超时性:@Transactional(timeout=30) //默认是30秒

  注意这里说的是事务的超时性而不是Connection的超时性,这两个是有区别的

(3)、事务的隔离级别:@Transactional(isolation = Isolation.READ_UNCOMMITTED)

  读取未提交数据(会出现脏读, 不可重复读) 基本不使用

(4)、回滚:

指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)

指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。

(5)、只读:@Transactional(readOnly=true)

该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。

例如:

@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class,timeout=1,isolation=Isolation.DEFAULT)    
public void saveUser(Map<String, String> map) throws Exception {    
        System.out.println("方法开始");    
    for (int i = 0; i < 500000; i++) {    
            System.out.println("*");    
        }    
     System.out.println("进入保存");    
     userDao.saveUser(map);    
     System.out.println("退出保存");    
} 

解释说明
事务的传播级别定义的是事务的控制范围,主要是父子事务之间的相互影响关系;事务的隔离级别定义的是事务读写的控制范围,主要是两个事务之间的相互影响关系。

传播级别:

1)、REQUIRED

如果当前方法已经在事务中,那么就以父事务执行,不需要新建事务;如果当前方法不在事务中,那么就为当前方法新建事务。回滚情况:父子方法中任何地方出现问题,都会全部回滚。

2)、SURPPORTED

如果当前方法已经在事务中,那么就以当前事务执行;如果当前方法不再事务中,那么就以非事务方式运行。如果运行在事务中,那么只要出现异常都会回滚。

3)、NOT_SURPPORTED

如果当前方法已经在事务中,那么就挂起当前事务,以非事务方式运行,方法执行完毕后,恢复事务;如果当前方法不再事务中,那么就以非事务方式执行。

4)、MANDATORY

强制以事务方式执行,如果当前方法不在事务中,那么会抛出异常。

5)、NEVER

与MANDATORY相反,强制以非事务方式执行,如果当前方法在事务中,那么会抛出异常。

6)、REQUIRED_NEW

与REQUIRED不同的是,无论该方法当前是不是在事务中,都会为自己新建一个事务。如果当前已经在事务中,那么会挂起父事务,为自己新建一个事务。父事务不影响它子事务的提交和回滚。

7)、NESTED

嵌套事务。理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。而Nested事务的好处是他有一个savepoint。

例如:

ServiceA {  
/**  
* 事务属性配置为 PROPAGATION_REQUIRED  
*/  
void methodA() {  
try {  
//savepoint  
ServiceB.methodB(); //PROPAGATION_NESTED 级别  
} catch (SomeException) {  
// 执行其他业务, 如 ServiceC.methodC();  
}  
}  
}

也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如ServiceC.methodC,继续执行,来尝试完成自己的事务。

猜你喜欢

转载自blog.csdn.net/lj_dreamone/article/details/79614521