@Transactional注解使用注意
- 必须用在public方法上。如果使用在别的方法上(比如protected,private)不会报错,但是事务不会生效
- 要在类方法上使用该注解(注解不能被继承),可以在接口上使用,但是需要配置相应的接口代理,所以不推荐在接口上使用
- 不要图省事,将注解放在类上声明,会使所有方法都有事务,为了性能考虑,最好的使用方式是在接口上使用
- 同类方法中调用(注解在类上),事务不生效;同样,A调B方法,B有A没有,事务同样不生效
- spring事务在抛异常的时候会回滚,但如果catch捕获了,事务无效。可以在catch加throw new RuntimeException
- 最后有个关键的一点:和锁同时使用需要注意:由于Spring事务是通过AOP实现的,所以在方法执行之前开启事务,之后提交事务逻辑。而synchronized代码块执行是在事务之内执行的,可以推断在synchronized代码块执行完时,事务还未提交,这时其他线程进入synchronized代码块后,读取的数据不是最新的。所以必须使synchronized锁的范围大于事务控制的范围,把synchronized加到Controller层或者
大于事务控制的范围,把synchronized加到Controller层或者大于事务边界的调用层
关于有@Transactional的函数之间调用会产生什么情况
同一个类中函数相互调用
同一个类AClass中,有两个函数aFunction、aInnerFunction。aFunction调用aInnerFunction。而且aFunction函数会被外部调用。
情况0: aFunction添加了@Transactional注解,aInnerFunction函数没有添加。aInnerFunction抛异常。
public class AClass {
@Transactional(rollbackFor = Exception.class)
public void aFunction() {
//todo: 数据库操作A(增,删,该)
aInnerFunction(); // 调用内部没有添加@Transactional注解的函数
}
private void aInnerFunction() {
//todo: 操作数据B(做了增,删,改 操作)
throw new RuntimeException("函数执行有异常!");
}
}
结果:两个函数操作的数据都会回滚。
情况1:两个函数都添加了@Transactional注解。aInnerFunction抛异常。
public class AClass {
@Transactional(rollbackFor = Exception.class)
public void aFunction() {
//todo: 数据库操作A(增,删,该)
aInnerFunction(); // 调用内部没有添加@Transactional注解的函数
}
&