@Transactional 注解使用
@Transactional
注解是java程序员使用频率很高的注解,但是很多人可能并没有很深入去了解,特别是刚开始编程的同学,可能习惯性的在方法上或者类上加上@Transactional
注解,就以为完事了。今天我们来讲讲使用@Transactional
注解使用要注意的地方
@Transactional 事务注解原理
@Transactional在面试中也是经常被问到的点。
@Transactional 的工作机制是基于 AOP
实现的,AOP 又是使用动态代理
实现的。
如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理,如果目标对象没有实现了接口,会使用 CGLIB 动态代理。
如果一个类或者一个类中的 public 方法上被标注@Transactional
注解的话,Spring 容器在启动的时候为其创建一个代理类,在调用被@Transactional
注解的 public
方法的时候,实际调用的是,TransactionInterceptor
类中的invoke()
方法。这个方法的作用是在目标方法之前开启事务,方法执行过程中如果遇到异常的时候回滚事务,方法调用完成之后提交事务。
@Transactional 的使用注意事项
- @Transactional注解到
public
方法上才有效,不推荐直接注解在类上 - 被@Transactional注解的方法必须被
spring
管理,否则无效 - 底层使用的数据库必须
支持事务
,否则无效
– 这里补充解释一下,在开发中,我们经常会把一段逻辑封装起来,如
public void freezeMemberVacation(FreezeMemberVacation freezeData, UmsMember currentMember) throws ServiceException {
XXXX
}
在这个方法上加@Transactional 是不生效的,因为这个方法没有加入spring管理。
但是如果这个方法是 被@Service
、@Component
、@Repository
或@Controller
管理的子方法
,便可以纳入spring管理。
- 最好加上
rollbackFor
和propagation
属性,否则有可能会失败 - 避免
同一个类
中调用 @Transactional 注解的方法,否则会失效 - 如果异常被
try-catch
,不会触发回滚 - 开启
多线程
任务时,事务会受影响,因为线程不属于spring托管