不要在接口上声明@Transactional ,而要在具体类的方法上使用 @Transactional 注解,否则注解可能无效。
不要在抽象方法的具体实现上声明@Transactional,比如一个父类,存在一个抽象方法A,在子类中实现此抽象方法A并声明@Transactional,父类中调用此抽象方法A,事务不生效。
不要将@Transactional放置在类级的声明中,放在类声明,会使得所有方法都有事务。@Transactional应该放在方法级别,不需要使用事务的方法,就不要放置事务,比如查询方法。否则对性能是有影响的。
使用了@Transactional的方法,对同一个类里面的方法调用, @Transactional无效(同类调用,注解失效)。比如有一个类Test,它的一个方法A,A再调用Test本类的方法B(不管B是否public还是private),但A没有声明注解事务,而B有。则外部调用A之后,B的事务是不会起作用的。(经常在这里出错)
使用了@Transactional的方法,只能是public,@Transactional注解的方法都是被外部其他(Service或Controller)调用才有效,故只能是public。故在 protected、private或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错,但事务无效。
Spring在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,Spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。
此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用方法之前就会启动Transaction。
然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动Transaction,我们看到的现象就是@Transactional注解无效。
Spring代理只会增强public的方法,所以注解加其他访问修饰符上不生效