尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SpringBoot事务失效的8种场景

SpringBoot事务失效的8种场景 SpringBoot让事务管理变得极其简单一个Transactional注解似乎就能搞定一切。但实际开发中事务莫名其妙不回滚的情况比比皆是。我整理了8种最常见的失效场景每一个都是血泪教训。一、方法不是publicTransactional基于AOP代理Spring默认只对public方法生效。如果你把注解加在private、protected或包级方法上事务不会启动也不会报错。很多人写了一个私有方法加事务调了半天发现根本没生效。解决确保事务方法为public。二、自调用this调用本类方法这是最经典的坑。在同一个类中方法A调用方法B即使B加了Transactional事务也不会生效。因为自调用走的是原始对象而不是代理对象。解决把B方法抽到另一个Bean中或者注入自身代理或者用AopContext.currentProxy()。三、异常被捕获没有抛出方法内部try-catch把异常吞了事务管理器感知不到异常自然不回滚。解决捕获后要么重新抛出要么手动TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。四、异常类型不对Spring默认只对RuntimeException和Error回滚。如果你抛的是检查异常如IOException事务不会回滚。解决使用Transactional(rollbackFor Exception.class)。五、数据库引擎不支持事务MySQL的MyISAM引擎不支持事务如果你建表时用了它注解再正确也没用。解决使用InnoDB引擎。这个坑在老旧项目中尤其常见。六、多线程调用事务信息保存在ThreadLocal中新线程无法获取父线程的事务上下文。如果你在事务方法中开新线程执行数据库操作新线程的操作不在同一个事务里。解决避免在事务中开线程或者把事务逻辑放在线程内部独立处理。七、传播行为配置错误Transactional(propagation Propagation.NOT_SUPPORTED)会挂起当前事务。如果你在需要事务的方法上配了SUPPORTS或NOT_SUPPORTED自然不会回滚。解决理解传播行为默认REQUIRED通常够用。八、Bean未被Spring管理自己new出来的对象即使方法上有Transactional也不会有代理事务失效。比如在工具类里直接new Service()调用。解决确保事务Bean由Spring容器管理通过依赖注入获取。额外补充只读事务中写操作Transactional(readOnly true)只是提示不一定阻止写入但某些数据库驱动会拒绝写操作导致异常。不要把只读事务用在写方法上。如何排查开启事务调试日志logging.level.org.springframework.transactionDEBUG。观察日志中有没有 “Creating new transaction” 或 “Participating in existing transaction”。如果没有说明事务根本没生效。结语事务失效的原因大多不是Spring的bug而是我们对代理机制、异常体系和传播行为的理解不够深。记住一个原则事务是基于代理的代理生效的前提是外部调用、public方法、异常抛出、Bean被管理。把这四点刻在脑子里能避开90%的坑。
返回列表