Spring事务传播机制
事务是逻辑处理原 性的保证 段,通过使 事务控制,可以极 地避免出现逻辑处理失败导致的脏数据等问题。 @Transactional
@Transactional是声明式事务的注解,可以被标记在类上、接口、方法上。 public @interface Transactional { @AliasFor("transactionManager") String value() default ""; //事务管理器,值为bean的名称,这个主要用于多事务管理器情况下指定。比如多数据源配置的情况下。 @AliasFor("value") String transactionManager() default ""; //事务的传播行为,默认值为Propagation.REQUIRED。 Propagation propagation() default Propagation.REQUIRED; //事务的隔离级别,默认是Isolation.DEFAULT。 Isolation isolation() default Isolation.DEFAULT; //事务的超时时间,单位为秒 int timeout() default -1; //用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。如果一个事务只涉及到只读,可以设置为true。 boolean readOnly() default false; //用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。默认是在RuntimeException和Error上回滚。 Class<? extends Throwable>[] rollbackFor() default {}; String[] rollbackForClassName() default {}; //和 rollbackFor 互补, 抛出指定的异常类型时不回滚事务,也可以指定多个异常类型。 Class<? extends Throwable>[] noRollbackFor() default {}; String[] noRollbackForClassName() default {}; }传播级别和使用场景
事务 传播级别 定义了事务的控制范围 public enum Propagation { REQUIRED(0), SUPPORTS(1), MANDATORY(2), REQUIRES_NEW(3), NOT_SUPPORTED(4), NEVER(5), NESTED(6); private final int value; private Propagation(int value) { this.value = value; } public int value() { return this.value; } }PROPAGATION_REQUIRED (默认)
如果上下 中已经存在事务,那么就加 到事务中执 ,如果当前上下 中不存在事务,则新建事务执 。 class C1(){ @Transactional(propagation = Propagation.REQUIRED) function A(){ C2.B(); } } class C2(){ @Transactional(propagation = Propagation.REQUIRED) function B(){ do something; } }
若B方法抛出异常,A方法进行捕获,A会抛出异常,因为C2标志回滚,C1标志提交,产生冲突。
若B方法抛出异常,B方法内部捕获,A、B都不会回滚。
若A或B抛出异常,但没有捕获,则A、B都回滚。
A、B可操作同一行记录,因为处在同一事务中。 PROPAGATION_MANDATORY
该级别的事务要求上下 中必须要存在事务,否则就会抛出异常!
能有效地控制上下 调 代码遗漏添加事务控制 。
如 段代码不能单独被调 执 ,但是 旦被调 ,就必须有事务包含的情况,就可以使 这个传播级别。 PROPAGATION_REQUIRES_NEW
每次都会新建 个事务,并且同时将上下 中的事务挂起,执 当前新建事务完成以后,上下 事务恢复再执 。 class C1(){ @Transactional(propagation = Propagation.REQUIRED) function A(){ C2.B(); } } class C2(){ @Transactional(propagation = Propagation.REQUIRE_NEW) function B(){ do something; } }
若B方法抛出异常,A方法进行捕获,B方法回滚,A方法不受B异常影响。
若B方法抛出异常,B方法进行捕获,A、B都不会回滚。
若A方法抛出异常,不会影响B正常执行。
若B方法抛出异常,A、B方法都没有处理,则A、B都会回滚。
A、B不可操作同一条记录,因为处于不同事务中,会产生死锁。 PROPAGATION_SUPPORTS
如果上下 存在事务,则 持事务加 事务,如果没有事务,则使 事务的 式执 。
通常是 来处理那些并 原 性的 核 业务逻辑操作 。 应 场景较少 。 PROPAGATION_NOT_SUPPORTED
若当前上下 中存在事务,则挂起事务,执 当前逻辑,结束后恢复上下 的事务。
可以将事务范围尽可能地缩 ,建议优先使用代码隔离的方式进行
个事务越 ,它存在的 险也就越多 PROPAGATION_NEVER
要求上下 中不能存在事务, 旦有事务,就抛出runtime异 PROPAGATION_NESTED
如果当前存在事务,则嵌套(savepoint)在当前事务中执行。如果当前没有事务,则新建一个事务,类似REQUIRE_NEW。