spring之@Transactional 简介

// 源码
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {

	@AliasFor("transactionManager")
	String value() default "";

	@AliasFor("value")
	String transactionManager() default "";

	String[] label() default {};

	Propagation propagation() default Propagation.REQUIRED;

	Isolation isolation() default Isolation.DEFAULT;

	int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

	String timeoutString() default "";

	boolean readOnly() default false;

	Class<? extends Throwable>[] rollbackFor() default {};

	String[] rollbackForClassName() default {};

	Class<? extends Throwable>[] noRollbackFor() default {};

	String[] noRollbackForClassName() default {};

}

1. @Transactional 属性

value

value 属性与 transactionManager属性互为别名,用于指定事务管理器。当存在多个数据源时,往往需要不同的数据源,使用不同的事物管理器,可以使用value属性,或者transactionManager属性指定具体的事物管理器。

transactionManager

@see value

propagation

事务的传播行为

假设当前有两个方法 A, B。方法A 调用了 方法B, A与B有都具有事务,当A 调用B 后,B的事务该怎样变化呢,这个就取决于设置的事务传播行为。事实上 B 的事务,大致有三种情况:第一 开启新的事务;第二 加入 A的事务;第三 以非事务的方式运行;
以下的例子均为 A 调用 B

  • PROPAGATION_REQUIRED:也是默认的事务传播行为。如果当前存在事务,则加入当前事务;如果当前不存在事务,则开启一个新的事务
    • 当前存在事务:A异常回滚时,B也会回滚;B异常回滚时,A也会回滚,同一个事务
    • 当前不存在事务:即 A 没开启事务,B会单独开启一个事务,当B回滚时,不会影响A, 当然 A中出现异常,也不会影响B;

  • PROPAGATION_SUPPORTS:如果当前存在事务,则加入当前事务(A,B同一个事务);如果当前不存在事务,则也不开启事务

  • PROPAGATION_MANDATORY:如果当前存在事务,则加入当前事务 (同一个事务);如果当前不存在事务,则抛出异常

  • PROPAGATION_REQUIRES_NEW:重新开启一个新事物;
    • 如果当前存在事务,当前事务对B不起作用,也就是当A发送异常时,只会回滚A中的数据,对B没有影响。但是如果B抛出了异常,且这个异常恰好满足A的回滚机制时,A会回滚。
    • 如果当前不存在事务:显然B不会影响A, 因为A不具有事务;A也不会影响B, 因为A中的异常,B也没法捕获

  • PROPAGATION_NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,当前事务只会对A生效,不会对B生效
  • PROPAGATION_NEVER:以非事务的方式运行,如果当前存在事务,抛出异常
  • PROPAGATION_NESTED 如果当前存在事务,则会作为当前事务的嵌套事务来继续运行。如果当前不存在事务,则会开启一个新事务。
    • 当前存在事务:当A 回滚时,B也会回滚;但是当B回滚时,不会影响A
    • 当前不存在事务:B会开启一个新事物,这个事务只作用与B, B回滚不会影响A

isolation

事务的隔离级别

事务的隔离级别即在多并发的情况下,多个事务之间的隔离程度

  • Isolation.DEFAULT 使用数据库默认的隔离级别。mysql 默认可重复读;oracle默认读已提交
  • Isolation.READ_UNCOMMITTED 读未提交
    • 允许读取还没提交的数据变更;这就可能造成脏读,幻读,不可重复读
    • 脏读:A 先修改了 table中的某条数据中的某个属性的值,但是还未提交数据,此时 B 同样查询了该属性值,就会导致 B查询出的是无用的数据。
    • 幻读:A读取了table中的一些数据,B在table中添加了一些数据,当A再次用相同的条件读取table中的数据,就会导致新查询出的数据多出几行,就像出现幻觉一样
    • 不可重复读:A 查询了table中的一些数据,B对这些数据进行了修改。当A 再次查询这些数据的时候,会导致两次查询出的数据不一样,导致不可重复读到原始的数据

  • Isolation.READ_COMMITTED 读以提交;可以避免脏读,但是幻读和不可重复读依然可能发生
  • Isolation.REPEATABLE_READ 可重复读;可以避免脏读和不可重复读,但是幻读可能发生
  • Isolation.SERIALIZABLE 序列化;可以避免脏读,幻读,不可重复读。但是严重影响程序性能

timeout

事务超时时间;即当事务运行时间超过 timeout时,会自动回滚事务,默认值为 -1 ,不设置超时时间

readOnly

只读;只允许事务进行查询操作,对于一次执行多条查询语句的,可以开启readOnly,可以保证整体读一致性。默认false

rollbackFor

事务回滚规则,接收指定异常进行回滚

  • 指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
  • 指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

rollbackForClassName

事务回滚规则

  • 指定单一异常类名称:@Transactional(rollbackForClassName=“RuntimeException”)
  • 指定多个异常类名称:@Transactional(rollbackForClassName={“RuntimeException”,“Exception”})

noRollbackFor

@see rollbackFor

noRollbackForName

@see rollbackForClassName

2. @Transactonal 作用范围

  1. 作用在类上:Transactional 对该类下所有public方法都生效
  2. 作用在 public方法上。但必须是 public修饰的方法
  3. 接口上;不推荐使用

3. @Transactional 失效的情况

  1. 被@Transactional 修饰的方法所在的类,没有被spring所管理。
  2. @Transactional 作用在 非 public方法上
  3. @Transactional 的事务传播行为设置错误
  4. @Transactional 的 rollbackFor属性设置错误
  5. 同一个类中调用的方法调用 @Transactional 修饰的方法。方法 A,B 属于同一个类,方法A 没有被 @Transactional 修饰,方法 B 被 @Transactional 修饰。 在 A 中调用 B。当外部的方法再调用A时,事务可能会失效。尽量将 @Transactional 修饰的方法抽离出来
  6. 异常被 catch 抓住,导致@Transactional 无法捕获异常
  7. 数据库引擎不支持事务
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Spring Boot中,@Transactional是一个注解,用于标记一个方法或类需要进行事务管理。事务是一组操作的逻辑单元,要么全部成功执行,要么全部回滚。使用@Transactional注解可以确保在方法执行期间,如果发生异常或错误,所有对数据库的操作都会回滚到事务开始之前的状态。 当我们在一个方法上添加@Transactional注解时,Spring会自动为该方法创建一个事务,并在方法执行之前开启事务,在方法执行之后根据方法的执行结果决定是提交事务还是回滚事务。如果方法执行成功,事务将会被提交,如果方法执行失败,事务将会被回滚。 除了在方法上使用@Transactional注解,我们还可以将它应用于类级别。当我们在类级别上添加@Transactional注解时,该类中的所有方法都将被包装在一个事务中。 需要注意的是,@Transactional注解默认只对未检查异常(RuntimeException及其子类)进行回滚,对于检查异常(Exception及其子类)不会回滚。如果需要对检查异常进行回滚,可以使用@Transactional(rollbackFor = Exception.class)来指定回滚的异常类型。 另外,@Transactional注解还可以接收一些参数,用于配置事务的传播行为、隔离级别、超时时间等。例如,@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 3600)。 总结一下,@Transactional注解是用于在Java Spring Boot中进行事务管理的注解,通过标记方法或类,可以确保一组操作要么全部成功执行,要么全部回滚。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值