隔离级别:
@Transactional(isolation =Isolation.READ_COMMITTED)
Isolation.DEFAULT
Isolation.READ_UNCOMMITTED
Isolation.READ_COMMITTED
Isolation.REPEATABLE_READ
Isolation.SERIALIZABLE
Spring事务的隔离级别和mysql事务的隔离级别不一致时,以spring的为准,当Spring默认隔离级别的时候,使用mysql的隔离级别
传播行为:
@Transactional(propagation = Propagation.REQUIRED)
1. REQUIRED(required要求):(默认)如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
2. SUPPORTS(supports支持):如果当前存在事务,则支持当前事务;如果当前没有事务,则以非事务方式继续运行。
3. MANDATORY(mandatory强制性的):如果当前存在事务,则支持当前事务;如果当前没有事务,则抛出异常。
4. REQUIRES_NEW(requires需要):无论当前是否存在事务,都创建一个新的事务,原来的事务挂起。
5. NOT_SUPPORTED:无论当前是否存在事务,都以非事务方式执行。
6. NEVER:无论当前是否存在事务,都以非事务方式执行,如果当前存在事务,则抛出异常。
7. NESTED(nested嵌套的):如果当前存在事务,则在该事务内嵌套创建一个新的事务;如果当前没有事务,则其行为等同于REQUIRED。
回滚规则:@Transactional(rollbackFor = Exception.class)
Error 类型和 RuntimeException 类型的异常会自动触发事务回滚,不需要特别指定。如果你想要忽略某些异常,使其不触发事务回滚,可以在 rollbackFor 参数中排除这些异常类型,例如 noRollbackFor = {MyException.class}
是否只读:
readOnly = flase
指定事务是否为只读事务,默认值为 false。
事务超时:
@Transactional(timeout = 10)
所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒,默认值为-1,这表示事务的超时时间取决于底层事务系统或者没有超时时间。
事务失效:
SpringAOP的自调用
当一个方法被标记了@Transactional 注解的时候,Spring 事务管理器只会在被其他类方法调用的时候生效,而不会在一个类中方法调用生效。
这是因为 Spring AOP 工作原理决定的。因为 Spring AOP 使用动态代理来实现事务的管理,它会在运行的时候为带有 @Transactional 注解的方法生成代理对象,并在方法调用的前后应用事物逻辑。如果该方法被其他类调用我们的代理对象就会拦截方法调用并处理事务。但是在一个类中的其他方法内部调用的时候,我们代理对象就无法拦截到这个内部调用,因此事务也就失效了。MyService 类中的method1()调用method2()就会导致method2()的事务失效。
@Service
public class MyService {
private void method1() {
method2();
//......
}
@Transactional
public void method2() {
//......
}
}
解决办法就是避免同一类中自调用或者使用 AspectJ 取代 Spring AOP 代理。
@Service
public class MyService {
private void method1() {
((MyService)AopContext.currentProxy()).method2(); // 先获取该类的代理对象,然后通过代理对象调用method2。
//......
}
@Transactional
public void method2() {
//......
}
}
@Transactional的使用注意事项总结
● @Transactional 注解只有作用到 public 方法上事务才生效,不推荐在接口上使用;
● 避免同一个类中调用 @Transactional 注解的方法,这样会导致事务失效;
● 正确的设置 @Transactional 的 rollbackFor 和 propagation 属性,否则事务可能会回滚失败;
● 被 @Transactional 注解的方法所在的类必须被 Spring 管理,否则不生效;
● 底层使用的数据库必须支持事务机制,否则不生效;