事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种。

一、声明式事务

在业务逻辑层接口的实现类中的相关方法上声明事物

@Transactional
@Override
public String interfaceTest(Map<String, Object> map) {
    // 事务的操作
    return null;
}

Transactional 注解的常用属性表:

二、编程式事务

   /**
     * 注入
     */
    @Autowired
    private DataSourceTransactionManager transactionManager;

@Override
    public String interfaceTest(Map<String, Object> map) {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        // 设置事务名称
        def.setName("test-Transactional");
        // 读写或只读事务、默认:读写
        def.setReadOnly(true);
        // 事务超时时间,默认:不超时 单位:秒
        def.setTimeout(10);
        /**
         * 设置事务的隔离级别
         *
         * 1、TransactionDefinition.ISOLATION_DEFAULT
         *    这是一个默认的隔离级别,默认使用数据库的隔离级别。
         * 2、TransactionDefinition.ISOLATION_READ_UNCOMMITTED
         *    这是事务最低的隔离界别,他允许别的事务可以看到这个事务未提交的数据。
         *    这种隔离级别可能会产生脏读,不可重复读和幻像读。
         * 3、TransactionDefinition.ISOLATION_READ_COMMITTED
         *    这个级别可以保证在数据提交以后才能被另个一个事务读取。
         *    这种隔离级别可以避免脏读,但是可能会出现不可重复读和幻读。
         * 4、TransactionDefinition.ISOLATION_REPEATABLE_READ
         *    这个级别可以禁止一个事务读取一个没有提交变化的行。
         *    这种隔离级别可以防止脏读和不可重复读,但是可能会出现幻读。
         * 5、TransactionDefinition.ISOLATION_SERIALIZABLE
         *    这种隔离级别可以防止脏读、不可重复读、幻读。
         *
         */
        def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
        /**
         * 设置事务的传播行为
         *
         * 1、TransactionDefinition.PROPAGATION_REQUIRED
         *    如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。默认值
         * 2、TransactionDefinition.PROPAGATION_REQUIRES_NEW
         *    创建一个新的事务,如果当前存在事务,则把当前的事务挂起。
         * 3、TransactionDefinition.PROPAGATION_SUPPORTS
         *    如果当前存在事务,则加入该事务,如果当前没有事务,则以非事务的方式继续运行。
         * 4、TransactionDefinition.PROPAGATION_NOT_SUPPORTED
         *    以非事务方式运行,如果当前存在事务,则把当前事务挂起。
         * 5、TransactionDefinition.PROPAGATION_NEVER
         *    以非事务方式运行,如果当前存在事务,则抛出异常。
         * 6、TransactionDefinition.PROPAGATION_MANDATORY
         *    如果当前存在事务、则加入该事务,如果当前没有事务,则抛出异常
         * 7、TransactionDefinition.PROPAGATION_NESTED
         *    如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行。
         *    如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
         */
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = transactionManager.getTransaction(def);
        try {
            //
            // 提交事务
            transactionManager.commit(transactionStatus);
        }catch (Exception e){
            // 回滚事务
            transactionManager.rollback(transactionStatus);
        }
        return null;
    }

三、对比

声明式事务管理方法只需要增加@Transactional注解即可,不需要依赖底层API进行编码。
声明事务管理就是使用 AOP 实现的,本质就是通过对目标方法执行前后进行拦截。

以下几种场景就可能导致声明式事务失效

1、@Transactional 应用在非 public 修饰的方法上。
2、@Transactional 注解属性 propagation 设置错误
3、@Transactional 注解属性 rollbackFor 设置错误
4、同一类中方法调用,导致@Transactional 失效。
5、异常被catch捕获,导致@Transactional 失效。
6、数据库引擎不支持事务。

以上几个问题,如果使用编程式事务的话,很多都是可以避免的。

阿里巴巴规约中也提到过: