Spring 声明事务中transactionAttributes属性 + - Exception 实现逻辑
下面是一段典型的Spring 声明事务的配置:
<bean id=“baseTxProxy” lazy-init=“true”class=“org.springframework.transaction.interceptor.TransactionProxyFactoryBean” scope=“singleton” abstract=“true”>
<property name=“transactionManager”>
<ref local=“transactionManager” />
</property>
<property name=“transactionAttributes”>
<props>
<prop key=“register*”>PROPAGATION_REQUIRED</prop>
<prop key=“trade*”>PROPAGATION_REQUIRED</prop>
<prop key=“cancel*”>PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED,-ApplicationException,+BusinessException</prop>
<prop key=“exe*”>PROPAGATION_REQUIRED</prop>
<prop key=“add*”>PROPAGATION_REQUIRED</prop>
<prop key=“persist*”>PROPAGATION_REQUIRED</prop>
<prop key=“remove*”>PROPAGATION_REQUIRED</prop>
<prop key=“del*”>PROPAGATION_REQUIRED</prop>
<prop key=“update*”>PROPAGATION_REQUIRED</prop>
<prop key=“gen*”>PROPAGATION_REQUIRED</prop>
<prop key=“finish*”>PROPAGATION_REQUIRED</prop>
<prop key=“get*”>PROPAGATION_REQUIRED,readOnly</prop>
<prop key=“find*”>PROPAGATION_REQUIRED,readOnly</prop>
<prop key=“query*”>PROPAGATION_REQUIRED,readOnly</prop>
<prop key=“select*”>PROPAGATION_REQUIRED,readOnly</prop>
<prop key=“is*”>PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
查阅相关spring 的资料后发现transactionAttributes的各种属性的意义如下:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
在Spring声明事务中,我们可以自定义方法的哪些Exception需要回滚,哪些Exception可以直接提交。
通过下面的配置:
<prop key="save*">PROPAGATION_REQUIRED,-aplicationException,+BusinessException</prop>
- 表示抛出该异常时需要回滚
+表示即使抛出该异常事务同样要提交
-ApplicationException :表示抛出ApplicationException 时,事务需要回滚。但不是说只抛出ApplicationException 异常时,事务才回滚,如果程序抛出RuntimeException和Error时,事务一样会回滚,即使这里没有配置。因为Spring中默认对所有的RuntimeException和Error都会回滚事务。
Spring中是如何实现这段逻辑的:
调用的是
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute.rollbackOn(Throwable ex)
public boolean rollbackOn(Throwable ex) {
if (logger.isTraceEnabled()) {
logger.trace("Applying rules to determine whether transaction should rollback on " + ex);
} RollbackRuleAttribute winner = null;
int deepest = Integer.MAX_VALUE; //配置文件中的回滚异常列表,当然去掉了-,只有name,commit的规则是另外一个对象
if (this.rollbackRules != null) {
for (RollbackRuleAttribute rule : this.rollbackRules) {
//使用抛出exception的className(全路径className)进行indexOf match
//如果没有match上会继续搜索superClass name进行match,到Throwable class为止
int depth = rule.getDepth(ex);
if (depth >= 0 && depth < deepest) {
deepest = depth;
winner = rule;
}
}
} if (logger.isTraceEnabled()) {
logger.trace("Winning rollback rule is: " + winner);
} // User superclass behavior (rollback on unchecked) if no rule matches.
if (winner == null) {
logger.trace("No relevant rollback rule found: applying default rules");
//如果没有match上,调用此方法继续match,判断instance of RuntimeException or Error
return super.rollbackOn(ex);
} return !(winner instanceof NoRollbackRuleAttribute);
}
rule.getDepth方法代码
因为使用的是className的全路径进行indexOf匹配,所以如果自定义异常是:com.abc.ApplicationException,你在xml配置文件中定义为:-abc,同样会match上,事务也会回滚,这一点需要注意。
另外一点,如何在xml中定义的是-Exception,这样只要class的全路径中包含Exception字段,如包名,也会匹配上。
public int getDepth(Throwable ex) {
return getDepth(ex.getClass(), 0);
} private int getDepth(Class exceptionClass, int depth) {
if (exceptionClass.getName().indexOf(this.exceptionName) != -1) {
// Found it!
return depth;
}
// If we've gone as far as we can go and haven't found it...
if (exceptionClass.equals(Throwable.class)) {
return -1;
}
return getDepth(exceptionClass.getSuperclass(), depth + 1);
}
super.rollbackOn(Throwable ex) 方法代码
很简单的一行代码,这就是为什么RuntimeException和Error也会回滚啦。
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
几次测试输出的debug日志:
[08/24 03:35:39] [DEBUG] RuleBasedTransactionAttribute: Applying rules to determine whether transaction should rollback on usertest.exception.BusinessException: Error
[08/24 03:35:39] [DEBUG] RuleBasedTransactionAttribute: Winning rollback rule is: RollbackRuleAttribute with pattern [BusinessException]
[08/24 03:35:39] [DEBUG] DataSourceTransactionManager: Triggering beforeCompletion synchronization
[08/24 03:35:39] [DEBUG] DataSourceTransactionManager: Initiating transaction rollback
[08/24 03:35:39] [DEBUG] DataSourceTransactionManager: Rolling back JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@1db05b2]
[08/24 03:35:39] [DEBUG] DataSourceTransactionManager: Triggering afterCompletion synchronization
[08/24 03:35:39] [DEBUG] TransactionSynchronizationManager: Clearing transaction synchronization
[08/24 03:35:39] [DEBUG] TransactionSynchronizationManager: Removed value [org.springframework.jdbc.datasource.ConnectionHolder@1833eca] for key [org.apache.commons.dbcp.BasicDataSource@4aa0ce] from thread [main]
[08/24 03:35:39] [DEBUG] DataSourceTransactionManager: Releasing JDBC Connection [org.apache.commons.dbcp.PoolableConnection@1db05b2] after transaction
[08/24 03:35:39] [DEBUG] DataSourceUtils: Returning JDBC Connection to DataSource [08/24 03:39:16] [DEBUG] TransactionInterceptor: Completing transaction for [usertest.dao.UsersDAO.testInsertAndUpdate] after exception: java.lang.Exception: Error
[08/24 03:39:16] [DEBUG] RuleBasedTransactionAttribute: Applying rules to determine whether transaction should rollback on java.lang.Exception: Error
[08/24 03:39:16] [DEBUG] RuleBasedTransactionAttribute: Winning rollback rule is: null
[08/24 03:39:16] [DEBUG] RuleBasedTransactionAttribute: No relevant rollback rule found: applying superclass default
[08/24 03:39:16] [DEBUG] DataSourceTransactionManager: Triggering beforeCommit synchronization
[08/24 03:39:16] [DEBUG] DataSourceTransactionManager: Triggering beforeCompletion synchronization
[08/24 03:39:16] [DEBUG] DataSourceTransactionManager: Initiating transaction commit
[08/24 03:39:16] [DEBUG] DataSourceTransactionManager: Committing JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@1db05b2]
[08/24 03:39:16] [DEBUG] DataSourceTransactionManager: Triggering afterCommit synchronization [08/24 03:41:40] [DEBUG] TransactionInterceptor: Completing transaction for [usertest.dao.UsersDAO.testInsertAndUpdate] after exception: usertest.exception.BusinessException: Error
[08/24 03:41:40] [DEBUG] RuleBasedTransactionAttribute: Applying rules to determine whether transaction should rollback on usertest.exception.BusinessException: Error
[08/24 03:41:40] [DEBUG] RuleBasedTransactionAttribute: Winning rollback rule is: RollbackRuleAttribute with pattern [Exception]
[08/24 03:41:40] [DEBUG] DataSourceTransactionManager: Triggering beforeCompletion synchronization
[08/24 03:41:40] [DEBUG] DataSourceTransactionManager: Initiating transaction rollback
[08/24 03:41:40] [DEBUG] DataSourceTransactionManager: Rolling back JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@1db05b2]
[08/24 03:41:40] [DEBUG] DataSourceTransactionManager: Triggering afterCompletion synchronization
[08/24 03:41:40] [DEBUG] TransactionSynchronizationManager: Clearing transaction synchronization
Spring 声明事务中transactionAttributes属性 + - Exception 实现逻辑的更多相关文章
- Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别
转: http://blog.csdn.net/it_man/article/details/5074371 Spring事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究,在此之 ...
- spring+mybatis事务的readonly属性无效
在Spring配置事务中设置的read-only="true"不起作用,仍可以执行写操作:但是其他的正常.查看了一下DataSourceTransactionManager这个类的 ...
- Spring配置事务中的 transactionAttributes 各属性含义及XML配置
转自:https://blog.csdn.net/z69183787/article/details/17161393 transactionAttributes 属性: PROPAGATION 事务 ...
- [spring]xml配置文件中bean属性的两种写法(p:configLocation <=> <property name="configLocation"/>)
1.当作bean节点的属性:p:configLocation: <!-- mybatis文件配置,扫描所有mapper文件 --> <bean id="sqlSession ...
- Spring声明事务管理
首先我们先了解事务,什么是事务? 简单来说就是要么全部成功,要么什么都不做. 为什么要使用事务? 比如说常用银行系统的例子,如果没有用事务,有人在存入钱的时候出了问题,那么银行系统数据库的数据没有改变 ...
- 日志配置文件读取spring boot配置文件中的属性
如果是读取 application.properties 这种spring boot的默认配置文件时 其中 scope固定为context 指明从上下文中获取, name 根据自己的意思给, sou ...
- [Spring] Spirng中的AOP进行事务的传播属性和事务隔离级别
通知注解 前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常) 返回后通知(@AfterReturning):在某连接点 ...
- 如何实现XA式、非XA式Spring分布式事务
Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...
- 非XA式Spring分布式事务
Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...
随机推荐
- Scrollview包裹布局问题。
输入框获取焦点,键盘弹出,背景图片上移: https://blog.csdn.net/wljian1/article/details/79962802 android:scrollbarThumbVe ...
- scrapy爬虫框架处理流程简介
1.SPIDERS的yeild将request发送给ENGIN2.ENGINE对request不做任何处理发送给SCHEDULER3.SCHEDULER( url调度器),生成request交给ENG ...
- mongodb-MYSQL
#encoding:utf8 import pymongoimport MySQLdbimport randomdef GetMongoData(): MyQuery = Mongo_Tab.find ...
- selenium之 chromedriver与chrome版本映射表(转载)
chromedriver版本 支持的Chrome版本 v2.34 v61-63 v2.33 v60-62 v2.32 v59-61 v2.31 v58-60 v2.30 v58-60 v2.29 v5 ...
- 20175314 《Java程序设计》第五周学习总结
20175314 <Java程序设计>第五周学习总结 教材学习内容总结 public接口可以被任意一个类实现,友好接口可被同一个包里的接口实现. Java不支持多重继承,即一个类只能有一个 ...
- scrapy -->CrawlSpider 介绍
scrapy -->CrawlSpider 介绍 1.首先,通过crawl 模板新建爬虫: scrapy genspider -t crawl lagou www.lagou.com 创建出来的 ...
- 贝叶斯---最大似然估计(高翔slam---第六讲 )
1.贝叶斯---最大似然估计 回顾一下第二讲的经典SLAM模型: 通过传感器(例如IMU)的运动参数u来估计运动(位姿x)[定位],通过相机的照片的观测参数z来估计物体的位置(地图y)[建图],都是有 ...
- 记一次python的任务调度模块apscheduler只在首次执行任务的情况
最近需要写个日更新的程序,用time.sleep()不能很好的控制任务的执行时间 于是,就使用了python的任务调度模块apscheduler,这个模块功能真的是很强大 具体的就不多讲了 将任务程序 ...
- 基于UML的中职班主任工作管理系统的分析与设计--文献随笔(二)
一.基本信息 标题:基于UML的中职班主任工作管理系统的分析与设计 时间:2016 出版源:遵义航天工业学校 关键字:中职学校; 班主任工作管理; UML建模 二.研究背景 问题定义:班主任是一项特殊 ...
- [Django] Window上通过IIS发布Django网站
网上的教程坑实在多,以下是本人亲测通过的: 需要解决的问题: 1.使用 python manage.py runserver 来运行服务器,只适用测试环境中使用,正式发布的服务,需要一个可以稳定而持续 ...