zoukankan      html  css  js  c++  java
  • mysql事务管理及spring声明式事务中主动异常抛出使数据库回滚

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

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

    <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方法如下

     @Override
        public int saveBudgetApplyInfo(BudgetApplyInfo budgetApplyInfo) throws Exception {
             budgetApplyInfoMapper.insert(budgetApplyInfo);
            if(1==1){
    
                throw new Exception();
            }
            return 1;
        }
    

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

    TransactionAspectSupport中发现这样一个方法
    /**
    	 * 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;
    				}
    			}
    		}
    	}
    

      上面的方法中有这么一段

    txInfo.transactionAttribute.rollbackOn(ex),这里是判断是否需要执行回滚操作的,跟踪rollbackOn方法最后会执行到
    DefaultTransactionAttribute中的rollbackOn方法
    /**
    	 * 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是不对的。这里只捕获运行时异常

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

      最后:个人还是比较喜欢基于注解的事务处理

  • 相关阅读:
    Python之异常篇 [待更新]
    python脚本工具 - 4 获取系统当前时间
    python脚本工具 - 3 目录遍历
    数字签名和数字证书到底是个神马玩意?
    CSRF攻击[转]
    Python之数据结构篇
    Python之模块篇
    Python之函数篇
    python脚本工具-2 去除扩展名后提取目录下所有文件名并保存
    python脚本工具-1 制作爬虫下载网页图片
  • 原文地址:https://www.cnblogs.com/wanglonghai/p/4866512.html
Copyright © 2011-2022 走看看