Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 356|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-30 13:54:44 | 显示全部楼层 |阅读模式

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

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

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-4 08:55 , Processed in 0.061325 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表