springboot service 事物回滚的问题

2017-11-22 13:43:01 +08:00
 strongme

现在有如下代码: https://gitee.com/strongme/codes/g0157y3zxhmn2bfurwvtc22 save 方法中某个位置抛出异常,整个事务没有回滚。这是什么问题呢?

7495 次点击
所在节点    Java
22 条回复
neoblackcap
2017-11-22 14:34:54 +08:00
抛 ServiceException,但是没有回滚?
JRay
2017-11-22 15:09:56 +08:00
不是应该抛出去嘛。。
strongme
2017-11-22 15:29:58 +08:00
@neoblackcap 朋友可以下下来工程跑跑试试,我要难受~~
weics
2017-11-22 16:34:12 +08:00
看下 ServiceException 继承的是 check 异常还是 uncheck 异常,顺便把 save 方法上面的 Transactional 去除,只保留 service 上面的注解
strongme
2017-11-22 16:43:24 +08:00
@weics 朋友你说的这两个我都试过了,但是还是不行
weics
2017-11-22 16:49:40 +08:00
@strongme
数据库的引擎是否支持代码回滚?
strongme
2017-11-22 16:55:21 +08:00
@weics 是支持的,别的 Service 没问题,就是 UserService
hustlike
2017-11-22 16:58:27 +08:00
你是不是要配置一个 transactionManager 的 bean ?
weics
2017-11-22 17:01:21 +08:00
@strongme
在别的 service 里面注入 user 的 dao 层,然后试试添加操作,看别的 service 能不能回滚,定位一下
tr0uble
2017-11-22 17:14:48 +08:00
看下 UserService 是不是一个代理类,回滚你明确指定了 ServiceException,是否有这种异常抛出
strongme
2017-11-22 17:56:14 +08:00
@tr0uble 我先查查什么叫代理类~~
strongme
2017-11-22 17:58:56 +08:00
@tr0uble 应该算是代理类
关键是其他的都正常····
就这个 UserService 不正常
lsyhyp
2017-11-22 18:07:40 +08:00
贴一下异常栈?
seaswalker
2017-11-23 07:40:03 +08:00
从哪里调的这个方法
strongme
2017-11-23 09:12:05 +08:00
@hustlike 有事务的 Service 有好多个呢,但是唯独这个 UserService 不起作用,有时间的话可以看看我传的那个代码~~好心塞
strongme
2017-11-23 09:12:25 +08:00
@weics 好办法!我去试试
strongme
2017-11-23 09:14:21 +08:00
@lsyhyp 朋友这到不是异常的问题,是事务的问题呢,异常是我手动故意抛出来的,要是测试事务回滚问题
strongme
2017-11-23 09:15:17 +08:00
@seaswalker 朋友是在 Controller 里面调用呢
kaka8wp
2017-11-23 09:44:43 +08:00
在 springBoot 使用事物时,发现事务并没有正常执行,没有进行回滚。
[java] view plain copy
@GetMapping("add")
@ResponseBody
@Transactional
public void add(String companyName,String name){
companyDao.add(companyName);
try {
userDao.addUser(name);
}catch (DuplicateKeyException e){//这里在数据库将 name 设置成 unique key
logger.error("添加失败。姓名:[ {} ],已存在",name);
return new MyException("添加失败,名字已存在");//自定义异常 继承 Exception
}
}


上述姓名重复时发现,公司名称依然添加成功,并没有进行回滚操作。

分析:默认 spring 事务只在发生未被捕获的 RuntimeException 时才回滚。
spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样 aop 代理才能捕获到方法的异常,才能进行回滚,默认情况下 aop 只捕获 RuntimeException 的异常,但可以通过配置来捕获特定的异常并回滚
换句话说在 service 的方法中不使用 try catch 或者在 catch 中最后加上 throw new runtimeexcetpion (),这样程序异常时才能被 aop 捕获进而回滚
解决办法:
1.首先确认数据库支持事务。即为 InnoDB。
方案一:手动回滚。给注解加上参数如:@Transactional(rollbackFor=Exception.class)
方案二:如上述分析。MyException 改为继承 RuntimeException 的异常。并且在 service 上层要继续捕获这个异常并处理
方案三:在 service 层方法的 catch 语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常

链接: http://blog.csdn.net/bestlovelymin/article/details/74942932
strongme
2017-11-23 14:37:07 +08:00
@kaka8wp 朋友我解决了,是 shiro 的问题,具体可以去仓库看看代码,是使用配置的问题,天生的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/408556

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX