声明式事务@Transactional 使用规范
开发过程中需要考虑事务一致性,主要要考虑是否需要开启事务、事务是否生效、是否能正确回滚。
1.@Transactional 注解应该只被应用到 public 方法上
如果Transactional注解应用在非public 修饰的方法上,Transactional将会失效。
2.选用合适的事务传播行为,正确配置propagation属性,默认为PROPAGATION_REQUIRED. 参考如下(未包含所有情况)
2.1.当方法内有多于一个操作,且需要保证事务一致时,使用PROPAGATION_REQUIRED
2.2.当方法内有多于一个操作,需要保持事务一致,且需要与父级方法的事务保持隔离时,使用PROPAGATION_REQUIRES_NEW
2.3.当方法内只有一个操作,且需要与父级方法的事务保持一致时,使用PROPAGATION_SUPPORTS
2.4.当方法内只有一个操作,且需要与父级方法的事务保持隔离时,使用PROPAGATION_NOT_SUPPORTED
3.考虑需要回滚的异常类型,正确配置rollbackFor属性和noRollbackFor属性
默认情况下,只回滚未检查异常(继承自 RuntimeException 的异常)或者 Error。
4.同一个类中方法调用,导致@Transactional失效
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。若同一类中的其他没有@Transactional注解的方法内部调用有@Transactional注解的方法,有@Transactional注解的方法的事务被忽略,不会发生回滚。
可采用自注入方式解决。
5.被catch,而没有被抛出的异常,将不会导致因该异常的回滚
6.@Transactional不建议用在处理时间过长的事务,可改用编程式事务处理方式来优化
@Transactional会一直持有数据库线程池的连接,造成不能及时返回。就是尽量使得事务的处理时间短。