昨天遇到一个非常奇怪的问题,在一个Service中使用@Transactional
注解的一个方法无论如何都不能开启事务。项目用的是Springboot和Mybatis Plus,权限验证用的是Shiro。Service层的伪代码如下:
@Transactional(rollbackFor = Exception.class)
public void register(String username, String password) {
Member member = new Member();
... ...
this.save(member);
MemberMessage memberMessage = new MemberMessage();
... ...
memberMessageService.save(memberMessage);
}
当memberMessage插入失败抛异常时,前面保存的member记录不会回滚。打断点发现,只要save(member)这行走完数据就直接插入,此时方法还没执行完,按道理事务应该还没提交,但是通过Navicat已经能够看到新增的记录了。怀疑是事务压根没开启,遂将logging.level.root
日志等级改为DEBUG发现压根就没开启事务。
找不到原因,往上层追查,这个方法是在Controller通过@Autowired
注入并调用的。之后我在这个Controller中注入其他Service添加测试方法testSave()
,Controller伪代码如下:
@Autowired
private MemberService memberService;
@Autowired
private ConfService confService;
@RequestMapping("/register")
public JsonResult register(String username, String password) {
confService.testSave();
// memberService.register(username, password);
return JsonResult.ok();
}
测试发现事务是生效的,且如果发生异常是能够回滚的,事务正常提交日志如下:
o.s.j.d.DataSourceTransactionManager : Creating new transaction with name [com.guitu18.service.base.ConfService$$EnhancerBySpringCGLIB$$82a30421.testSave]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Exception
o.s.j.d.DataSourceTransactionManager : Acquired Connection [com.mysql.jdbc.JDBC4Connection@10d912c1] for JDBC transaction
o.s.j.d.DataSourceTransactionManager : Switching JDBC Connection [com.mysql.jdbc.JDBC4Connection@10d912c1] to manual commit
o.s.j.d.DataSourceTransactionManager : Participating in existing transaction
o.s.j.d.DataSourceTransactionManager : Participating in existing transaction
org.mybatis.spring.SqlSessionUtils : Creating a new SqlSession
org.mybatis.spring.SqlSessionUtils : Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@734d6117]
o.m.s.t.SpringManagedTransaction : JDBC Connection [com.mysql.jdbc.JDBC4Connection@10d912c1] will be managed by Spring
c.g.mapper.base.ClanPlayerMapper.insert : ==> Preparing: INSERT INTO conf ( name, value ... ) VALUES ( ?, ? )
c.g.mapper.base.ClanPlayerMapper.insert : ==> Parameters: 123(String), 45(String)
c.g.mapper.base.ClanPlayerMapper.insert :
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?