Transactional

@Transactional

Spring @Transactional

@Transactional 注解中中几个比较重要的属性:

public @interface Transactional {

    // REQUIRED: 0,
    // SUPPORTS: 1,
    // MANDATORY: 2,
    // REQUIRES_NEW: 3,
    // NOT_SUPPORTED: 4,
    // NEVER: 5,
    // NESTED: 6
    Propagation propagation() default Propagation.REQUIRED;

    // DEFAULT: -1
    // READ_UNCOMMITTED: 1,
    // READ_COMMITTED: 2,
    // REPEATABLE_READ: 4,
    // SERIALIZABLE: 8
    Isolation isolation() default Isolation.DEFAULT;

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

    // 从这一点设置的时间点开始(时间点a)到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据)
    // 注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务
    boolean readOnly() default false;

    // 超时,事务是否发生回滚
    int timeout default -1;

}

事务传播属性 Propagation

  • REQUIRED: 有事务,加入事务,放到一个事务中执行,有异常一起回滚;没有就新创建一个事务。
  • REQUIRES_NEW: 无论有没有事务,都会新启一个事务,如果原来有,老的挂起,有异常互不干扰。
  • SUPPORTS: 有事务,加入事务,放到一个事务中执行,有异常一起回滚;否则不创建事务。
  • MANDATORY: 必须在一个已有事务中执行,否则抛出异常。
  • NEVER: 必须在一个没有事务中执行,否则抛出异常。
  • NOT_SUPPORTED: 不开启事务,并挂起任何存在的事务。
  • NESTED: 如果有事务运行,就作为这个事务的嵌套事务运行;如果没有活动事务,则按REQUIRED属性执行。

@Transactional 使用注意事项

  • @Transactional 只能应用到 public 方法才有效
  • @Transactional 不建议用在处理时间过长的事务
  • 一个有 @Transactional 的方法被没有 @Transactional 方法调用时,会导致 Transactional 作用失效。
  • 默认配置下,Spring 只有在抛出的异常为运行时 unchecked 异常时才回滚该事务,也就是抛出的异常为 RuntimeException 的子类(Errors也会导致事务回滚),而抛出 checked 异常则不会导致事务回滚 。可通过 @Transactional rollbackFor 进行配置。

手动设置事务回滚

// 事务管理器
@Autowired
private DataSourceTransactionManager transactionManager;

@Transactional
public void save(User user) {
    // 创建一个事务
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    // 显式设置事务名称是只能通过编程完成的操作
    def.setName("SomeTxName");
    // 设置事务策略
    // 支持当前交易;如果不存在,请创建一个新的。类似于同名的EJB事务属性。这通常是事务定义的默认设置, 并且通常定义事务同步作用域。
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    // 开始事务
    TransactionStatus status = transactionManager.getTransaction(def);
    try {
        // 在这里执行您的业务逻辑
        // db操作
        // 提交事务
        transactionManager.commit(status);
    } catch (Exception ex) {
        // 事务回滚
        transactionManager.rollback(status);
        throw ex;
    }
}