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" />

  最后:個人還是比較喜歡基於注解的事務處理

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM