Spring事务异常回滚,捕获异常不抛出就不会回滚(转载) 解决了我一年前的问题
最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......
为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志。但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚。
例:
类似这样的方法不会回滚 (一个方法出错,另一个方法不会回滚) :
if(userSave){
try {
userDao.save(user);
userCapabilityQuotaDao.save(capabilityQuota);
} catch (Exception e) {
logger.info("能力开通接口,开户异常,异常信息:"+e);
}
}
下面的方法回滚(一个方法出错,另一个方法会回滚):
if(userSave){
try {
userDao.save(user);
userCapabilityQuotaDao.save(capabilityQuota);
} catch (Exception e) {
logger.info("能力开通接口,开户异常,异常信息:"+e);
throw new RuntimeException();
}
}
或者:
if(userSave){
try {
userDao.save(user);
userCapabilityQuotaDao.save(capabilityQuota);
} catch (Exception e) {
logger.info("能力开通接口,开户异常,异常信息:"+e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
为什么不会滚呢??是对Spring的事务机制就不明白。!!
默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚。
spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过
配置来捕获特定的异常并回滚
换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚
解决方案:
方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理
方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常(现在项目的做法)
参考博客 Spring事务管理只对出现运行期异常进行回滚 http://blog.csdn.net/abc19900828/article/details/39497631
spring事物传播机制和隔离级别 http://blog.csdn.net/hijiankang/article/details/9174461
spring事务处理详解 http://blog.csdn.net/u013628152/article/details/47980811
1:Java包含两种异常:checked异常和unchecked异常。
checked和unchecked异常之间的区别是:
Checked异常必须被显式地捕获try-catch-finally,而unchecked异常则可以不必捕获或抛出。
Checked异常继承java.lang.Exception类。Unchecked异常继承自java.lang.RuntimeException类。
2:Mysql 存储引擎中InnoDB与Myisam的主要区别
事务处理方面:innodb 支持事务功能,myisam 不支持。
Myisam 的执行速度更快,性能更好。
engine = innodb 和 engine = myisam
可使用下述语句之一检查表的表类型:
SHOW TABLE STATUS LIKE ‘tbl_name’;
SHOW CREATE TABLE tbl_name;
使用下述语句,可检查mysqld服务器支持的存储引擎:
SHOW ENGINES;
3:spring事务处理
throw new RuntimeException(“xxxxxxxxxxxx”); 默认事务回滚
throw new Exception(“xxxxxxxxxxxx”); 默认事务不回滚
Spring的AOP即声明式事务管理默认是针对unchecked exception回滚。也就是默认对RuntimeException()异常或是其子类进行事务回滚;
checked异常,throw new Exception默认不会回滚
若想让checked异常或者自定义异常回滚
(1)配置文件方式
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="update*" no-rollback-for="IOException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" rollback-for="com.cn.untils.exception.MyException"/>
</tx:attributes>
</tx:advice>
(2)注解方式
@Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = MyException.class)
不起作用:
@Transactional
public void addAdmin(Admin admin) throws Exception {
try {
this.adminDao.add(admin);
admin.setUsername("123456789012345");
this.adminDao.update(admin);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("测试!");
}
}
起作用
@Transactional(rollbackFor = Exception.class)
public void addAdmin(Admin admin) throws Exception {
try {
this.adminDao.add(admin);
admin.setUsername("123456789012345");
this.adminDao.update(admin);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("测试!");
}
}
起作用
@Transactional
public void addAdmin(Admin admin) {
try {
this.adminDao.add(admin);
admin.setUsername("123456789012345");
this.adminDao.update(admin);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("测试!");
}
}
完整写法:
@Transactional(rollbackFor = RuntimeException.class)
public void addAdmin(Admin admin) {
try {
this.adminDao.add(admin);
admin.setUsername("123456789012345");
this.adminDao.update(admin);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("测试!");
}
Spring事务异常回滚,捕获异常不抛出就不会回滚(转载) 解决了我一年前的问题的更多相关文章
- Spring事务异常回滚,捕获异常不抛出就不会回滚
最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了....... 为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常 ...
- 【转】Spring事务异常回滚,捕获异常不抛出就不会回滚
最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了....... 为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异 ...
- spring事物回滚机制 (事务异常回滚,捕获异常不抛出就不会回滚)
当异常被捕获catch的时候,spring的事物则不会回滚 为什么不会滚呢?? spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常 ...
- Spring事务异常回滚
最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了....... 为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常 ...
- 异常如果一直被throws抛出的话就会被jvm异常处理器处理了
异常如果一直被throws抛出的话就会被jvm异常处理器处理了,这时jvm会跳出正常运行状态. 异常如果一直被throws抛出的话就会被jvm异常处理器处理了,这时jvm会跳出正常运行状态. 异常如果 ...
- spring事务 异常回滚
spring事务回滚 可抛出自定义继承自RuntimeException
- Spring事务异常rollback-only
转自:https://blog.csdn.net/sgls652709/article/details/49472719 前言 在利用单元测试验证spring事务传播机制的时候出现了下面的异常: Tr ...
- Spring事务异常rollback-only 笔记
造成以上异常的原因情形: 在spring里面我们配置了事务的传播机制是REQUIRED,所以这两个事务最终会合并成一个事务.当a方法调用b方法时,程序中a方法中由于某某原因导致抛出异常(或者明确将该事 ...
- hibernate整合spring事务异常
Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushM ...
随机推荐
- [置顶] Codeforces Round #190 (Div. 2)(完全)
好久没有写博客了,一直找不到有意义的题可以写,这次也不算多么有意义,只是今天是比较空的一天,趁这个时候写一写. A. B. 有一点贪心,先把每个拿去3的倍数,余下0或1或2,然后三个一起拿. 对于以上 ...
- HDU 1757 A Simple Math Problem(矩阵高速幂)
题目地址:HDU 1757 最终会构造矩阵了.事实上也不难,仅仅怪自己笨..= =! f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 ...
- flexigrid 修改json格式
1.修改默认的json格式为key:value 修改前 rows: [{id:'ZW',cell:['ZW','ZIMBABWE','Zimbabwe','ZWE','716']},{id:'ZW', ...
- Hibernate征途(三)之CRUD
上篇博客<Hibernate征途(二)之基础与核心>介绍了Hibernate的基础内容和核心内容,这篇博客简单实践一下.第一篇博客也说过Hibernate是一种JDBC的简化方案,既然是和 ...
- CSS Transform让百分比宽高布局元素水平垂直居中
很早以前了解过当元素是固定宽度和高度的时候,水平垂直高居中的方法可以设置margin的负值来使其居中,这个负值是元素的宽和高的一半,比如宽高是100px,那么就用margin-left:-50px;m ...
- taobao面试要点
第一: 其中有几个点必问,JVMGC深层机制.类加载,包括Tomcat和Jboss的.线程相关的如离线锁,互斥同步,java主线程和工作线程机制,concurrent包下的锁和sync关键字一些区别, ...
- MVC3学习随记一
最近才接触mvc,也是才接触linq语法,还有EntiyFramework,个人感觉这种开发模式还是挺不错的,随手记点笔记,简单做个增删改查吧 一.实例化上下文ObjectContext: 引用空间那 ...
- 解决 Boot Camp 虚拟机升级到 Windows 10 后 Parallels Desktop 不能识别的问题
最近几天 Win10 正式版开始推送了,对于喜欢折腾的博主,在第一时间就把 Mac 中 Boot Camp 从 Win7 升级到 Win10,初步体验还不错,等博主用过一段时间之后,再来给大家分享使用 ...
- NSDate 的一些操作(比较、创建、在现有date加减一定时间等)
创建当前时间 NSDate *date = [NSDate date]; 从现在开始的24小时 NSTimeInterval a_day = 24*60*60; NSDate *tomorrow = ...
- effective c++ 条款06 不想自动生成函数,就明确拒绝
编辑器会主动的生成三个/五个函数,如果不需要我们应该主动拒绝 使用私有属性来拒绝 ``` include int main() { return 0; } ``` 使用继承的方式来拒绝