springboot @transactional junit测试踩坑记

直接先上结论吧,简洁明了

  1. 需要回滚不要在测试方法上使用@Rollback,用@Transactional即可
  2. 如果采用了读写分离配置,那么千万不要在测试查询的方法上加回滚事务标记,否则只会经过写库
  3. 无论从规范角度还是实际结果角度,@Transactional标记一定不要偷懒标注在实现类上,一来会影响查询的效率,二来有时会不能回滚。因此都注解在方法上错不了,或者采用aop统一拦截

针对@transactional注解,再进行复习

@Transactional 加于private方法, 无效
@Transactional 加于未加入接口的public方法, 再通过普通接口方法调用, 无效
@Transactional 加于接口方法, 无论下面调用的是private或public方法, 都有效
@Transactional 加于接口方法后, 被本类普通接口方法直接调用, 无效
@Transactional 加于接口方法后, 被本类普通接口方法通过接口调用, 有效
@Transactional 加于接口方法后, 被它类的接口方法调用, 有效
@Transactional 加于接口方法后, 被它类的私有方法调用后, 有效
  • 一个功能是否要事务,必须纳入设计、编码考虑。不能仅仅完成了基本功能就ok。
  • 如果加了事务,必须做好开发环境测试(测试环境也尽量触发异常、测试回滚),确保事务生效。
  • 不要图省事,将@Transactional放置在类级的声明中,放在类声明,会使得所有方法都有事务。故@Transactional应该放在方法级别,不需要使用事务的方法,就不要放置事务,比如查询方法。否则对性能是有影响的
  • 使用了@Transactional的方法,只能是public,@Transactional注解的方法都是被外部其他类调用才有效,故只能是public。道理和上面的有关联。故在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错,但事务无效。
  • 使用了@Transactional的方法,对同一个类里面的方法调用, @Transactional无效。比如有一个类Test,它的一个方法A,A再调用Test本类的方法B(不管B是否public还是private),但A没有声明注解事务,而B有。则外部调用A之后,B的事务是不会起作用的。(经常在这里出错)

还有就是:

Spring的默认的事务规则是遇到运行异常(RuntimeException)和程序错误(Error)才会回滚。如果想针对非检测异常进行事务回滚,可以在@Transactional 注解里使用rollbackFor属性明确指定异常。

例子:

@Transactional(rollbackFor = Exception.class)
public void addUser() throws Exception {
    // 先增加余额
    userMapper.addUser();
    // 然后遇到故障
    throw new SQLException("发生异常了..");
}

日常针对事务等机制,其实有很多坑,要么就是没遇到,要么就是还没发现,希望日常大家针对事务这块有更深的理解。

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据