原框架太陈旧,在升级hibernate,并集成druid连接池,升级springboot版本等一系列操作之后,突然发现的项目中事务失效,导致throw异常后,部分提交未回滚 也不清楚是什么原因
于是,又开始排查
先看部分异常信息
at com.fengshun.sc.service.UseService$$FastClassBySpringCGLIB$$36140d0a.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) ~[spring-tx-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
其中可以看到事务的提交在org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction当中,我进进入看看。
可以看到,completeTransactionAfterThrowing方法来执行回滚操作。再进去
具体回滚在这里 txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
然而我未回滚的原因是,transactionManager为空,这是怎么回事,@EnableTransactionManagement也声明了呀?不过声明@EnableTransactionManagement也是让springboot自动给我们创建TransactionManager事务管理器,那好,没有就创建一个实例呗,新建一个Config配置类,并手动创建transactionManager。
@Configuration
public class DruidConfig {
@Bean
@ConditionalOnMissingBean
public PlatformTransactionManager transactionManager(@Qualifier("entityManagerFactory") EntityManagerFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory.unwrap(SessionFactory.class));
return transactionManager;
}
}
好,运行,OK。解决!
再给大家提供一下其它解决参考
0.声明式开启事务,检查一下是否在入口加上了@EnableTransactionManagement 注解
1.异常是否被内部捕获,被内部捕获而未throw 异常,导致无法回滚
2.@Transactional应定义在public的方法/类/接口上 ,检查无误
3.@Transactional所定义的方法非类内部调用(@Transactional本质是代理实现,而同一个类内部方法间调用不会走代理,可以用@Lazy把自身类注入一个实例进行调用)
总结,遇到程序问题,多思考 百度的答案千篇一律,但问题的产生也千奇百怪,我的解决方案不一定适用于你,但解决的思路可以参考延续
写的潦草,着急下班。见谅