mysql事务管理及spring声明式事务中主动异常抛出使数据库回滚

mysql的引擎常用的有两个,一个MyISAM,另一个是InnoDB,mysql默认的为MyISAM,而InnoDB才是支持事务的。所以一般需要修改下,如何修改就不说了。

   事务需要依赖数据库,好久没使用声明式事务,今天试了下。关键配置如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
< tx:advice  id="transactionAdvice" transaction-manager="transactionManager">
         < tx:attributes >
             < tx:method  name="add*" propagation="REQUIRED" />
             < tx:method  name="append*" propagation="REQUIRED" />
             < tx:method  name="insert*" propagation="REQUIRED" />
             < tx:method  name="save*" propagation="REQUIRED" />
             < tx:method  name="update*" propagation="REQUIRED" />
             < tx:method  name="modify*" propagation="REQUIRED" />
             < tx:method  name="edit*" propagation="REQUIRED" />
             < tx:method  name="delete*" propagation="REQUIRED" />
             < tx:method  name="remove*" propagation="REQUIRED" />
             < tx:method  name="tx*" propagation="REQUIRED" />
             < tx:method  name="repair" propagation="REQUIRED" />
             < tx:method  name="delAndRepair" propagation="REQUIRED"   />
 
             < tx:method  name="get*" propagation="SUPPORTS" />
             < tx:method  name="find*" propagation="SUPPORTS" />
             < tx:method  name="load*" propagation="SUPPORTS" />
             < tx:method  name="search*" propagation="SUPPORTS" />
             < tx:method  name="datagrid*" propagation="SUPPORTS" />
 
             < tx:method  name="*" propagation="SUPPORTS" />
         </ tx:attributes >
     </ tx:advice >
     < aop:config >
         < aop:pointcut  id="transactionPointcut" expression="execution(* com.wondersgroup.employeeBenefits.*.*.service..*Impl.*(..))" />
         
         <!-- com.wondersgroup.benefit.*.core.service..*Impl.*(..) -->
         < aop:advisor  pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
     </ aop:config >

  事务配置好之后再service中手动抛了个exception,结果没有回滚,service方法如下

1
2
3
4
5
6
7
8
9
@Override
    public  int  saveBudgetApplyInfo(BudgetApplyInfo budgetApplyInfo)  throws  Exception {
         budgetApplyInfoMapper.insert(budgetApplyInfo);
        if ( 1 == 1 ){
 
            throw  new  Exception();
        }
        return  1 ;
    }

  跟着断点一步步进去查看原因

TransactionAspectSupport中发现这样一个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
      * Handle a throwable, completing the transaction.
      * We may commit or roll back, depending on the configuration.
      * @param txInfo information about the current transaction
      * @param ex throwable encountered
      */
     protected  void  completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
         if  (txInfo !=  null  && txInfo.hasTransaction()) {
             if  (logger.isTraceEnabled()) {
                 logger.trace( "Completing transaction for ["  + txInfo.getJoinpointIdentification() +
                         "] after exception: "  + ex);
             }
             if  (txInfo.transactionAttribute.rollbackOn(ex)) {
                 try  {
                     txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                 }
                 catch  (TransactionSystemException ex2) {
                     logger.error( "Application exception overridden by rollback exception" , ex);
                     ex2.initApplicationException(ex);
                     throw  ex2;
                 }
                 catch  (RuntimeException ex2) {
                     logger.error( "Application exception overridden by rollback exception" , ex);
                     throw  ex2;
                 }
                 catch  (Error err) {
                     logger.error( "Application exception overridden by rollback error" , ex);
                     throw  err;
                 }
             }
             else  {
                 // We don't roll back on this exception.
                 // Will still roll back if TransactionStatus.isRollbackOnly() is true.
                 try  {
                     txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                 }
                 catch  (TransactionSystemException ex2) {
                     logger.error( "Application exception overridden by commit exception" , ex);
                     ex2.initApplicationException(ex);
                     throw  ex2;
                 }
                 catch  (RuntimeException ex2) {
                     logger.error( "Application exception overridden by commit exception" , ex);
                     throw  ex2;
                 }
                 catch  (Error err) {
                     logger.error( "Application exception overridden by commit error" , ex);
                     throw  err;
                 }
             }
         }
     }

  上面的方法中有这么一段

1
txInfo.transactionAttribute.rollbackOn(ex),这里是判断是否需要执行回滚操作的,跟踪rollbackOn方法最后会执行到
DefaultTransactionAttribute中的rollbackOn方法
1
2
3
4
5
6
7
8
/**
      * The default behavior is as with EJB: rollback on unchecked exception.
      * Additionally attempt to rollback on Error.
      * <p>This is consistent with TransactionTemplate's default behavior.
      */
     public  boolean  rollbackOn(Throwable ex) {
         return  (ex  instanceof  RuntimeException || ex  instanceof  Error);
     }

  看到这里,应该都清楚了。。。自己主动抛异常Exception是不对的。这里只捕获运行时异常

1
RuntimeException 及Error,所以我们测试时不可以直接抛Exception,而应该换成
1
RuntimeException 。当然。也可在xml中指定rollback- for
1
< tx:method  name="add*" propagation="REQUIRED" rollback-for="Exception" />

猜你喜欢

转载自blog.csdn.net/lishk314/article/details/79158125