项目中遇到的问题:
某一天突然发现事务出现异常不会回滚了,原因是shiro
的bean
先于Spring
事务将userService
实例化了,结果导致spring
事务初始化时好无法扫描到该bean
,导致这个bean
上没有绑定事务,导致事务无效。UserRealm改成注入userMapper就好了。
一.排查bug过程:
- 数据库的引擎是否是
innoDB
(可以用show engines; 查看数据库引擎) - 启动类上是否加入
@EnableTransactionManagement
注解 - 方法是否为
public
- 是否是因为抛出了
Exception
等checked
异常
二.运行时问题排查:
在上面4个原因检查时,发现将已有的service
类 copy下现在有两个除了名字其他都一模一样的类,这时运行下发现,在原来的类中@Transational
失效,在新copy中的类中@Transational
就起效了,这个问题好莫名奇妙,什么都没改就一个有效一个无效,现在的思路就是比较下这两个类在运行时有什么不同
通过log发现打出了一下信息,说是jdbc
的connection
不是Spring
管的
而正常回归的service类则是,调用了 JtaTransactionManager
类,而且 spring
是管理jdbc
的connection
的
通过这个分析,可以知道这spring
对于这两个类的处理是不一样的,应该是spring代理或者初始化的问题,翻了下log
发现service
在ProxyTransactionManagementConfiguration
配置之前就被创建了,那应该是这里的问题了,这里就要分析下service
为啥提前被创建了,发现在开始启动的是shiro
,而shiro
中有个realm
中引用了这些服务,所以这些服务在Transaction
创建扫描之前创建了
引发问题原因总结
导致问题的真正原因是bean
创建顺序问题,解决问题方法就是,在Transaction
之后创建service
。
解决方法一:
在realm
引用的service
服务上加@lazy
注解
解决方法二:
把在UserRealm注入的UserService换成UserMapper就可以