Spring事务管理(三) 编程式事务管理

 2022-09-13
原文地址:https://blog.51cto.com/andywuchuanlong/1362415

上一篇写到spring的声明式事务管理

spring同样也提供两种编程式事管理

1.使用TransactionTemplate

2.直接使用一个PlatformTransactionManager实现

如果使用编程式事务管理的方式,应该尽量采用TransactionTemplate

TransactionTemplate采用与spring中别的模板(如jdbcTemplate)同样的方法,它使用回调机制,将应用代码从资源获取和释放代码中解放出来,这样写出的代码是目的驱动的,把精力集中在开发者想做的事情上面。但是使用TransactionTemplate绝对会增加你的代码与spring事务框架和api间的耦合,具体的事务管理方式还是要根据不同的情况选择。

如下:

    public class SimpleService implements Service {
    in this instance
      private final TransactionTemplate transactionTemplate;
    PlatformTransactionManager
      public SimpleService(PlatformTransactionManager transactionManager) {
        Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");
        this.transactionTemplate = new TransactionTemplate(transactionManager);
      }
      public Object someServiceMethod() {
        return transactionTemplate.execute(new TransactionCallback() {
          public Object doInTransaction(TransactionStatus status) {
            updateOperation1();
            return resultOfUpdateOperation2();
          }
        });
      }
    }

如果你不需要返回值,也可以创建一个TransactionCallbackWithoutResult 的匿名类

    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
      protected void doInTransactionWithoutResult(TransactionStatus status) {
        updateOperation1();
        updateOperation2();
      }
    });

回调方法中的代码可以通过TransactionStatussetRollbackOnly() 方法来回滚事务

    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
      protected void doInTransactionWithoutResult(TransactionStatus status) {
        try {
          updateOperation1();
          updateOperation2();
        } catch (SomeBusinessExeption ex) {
          status.setRollbackOnly();
        }
      }
    });

诸如传播模式、隔离等级、超时等等的事务设置都可以在TransactionTemplate中或者通过配置或者编程式地实现

    public class SimpleService implements Service {
      private final TransactionTemplate transactionTemplate;
      public SimpleService(PlatformTransactionManager transactionManager) {
        Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");
        this.transactionTemplate = new TransactionTemplate(transactionManager);
        this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
        this.transactionTemplate.setTimeout(30); // 30 seconds
      }
    }

TransactionTemplate 实例是线程安全的,任何状态都不会保存,TransactionTemplate 会维护配置的状态,所以当一些类共享一个单独的TransactionTemplate实例时候,不需要考虑安全性的问题,但是如果一个类需要不同配置的TransactionTemplate,比如不同的隔离登记,那就需要创建两个不同的的TransactionTemplate

第二种方式是PlatformTransactionManager

我们可以直接使用PlatformTransactionManager管理我们的事务,只需要通过bean的应用,简单的把正在使用的PlatformTransactionManager传递给bean,然后,使用TransactionDefinitionTransactionStatus对象,可以启动,回滚和提交事务,

    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setName("SomeTxName");
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    TransactionStatus status = txManager.getTransaction(def);
    try {
       
    }
    catch (MyException ex) {
      txManager.rollback(status);
      throw ex;
    }
    txManager.commit(status);