1.5。程序化事务管理

1.5。程序化事务管理

Spring框架通过使用以下两种方式提供程序化事务管理的方法:

  1. TransactionTemplate或TransactionalOperator。

  2. 直接使用TransactionManager实现。

Spring团队通常推荐TransactionTemplate用于命令式流中的程序化事务管理,而TransactionalOperator用于响应代码。第二种方法类似于使用JTA UserTransaction API,尽管异常处理不那么麻烦。

1.5.1。使用TransactionTemplate

TransactionTemplate采用与其他Spring模板(如JdbcTemplate)相同的方法。 它使用一种回调方法(使应用程序代码不必进行样板获取和释放事务性资源),并生成意向驱动的代码,因为您的代码仅专注于您要执行的操作。

如以下示例所示,使用TransactionTemplate绝对链接可将您与Spring的事务基础结构和API结合使用。程序化事务管理是否适合您的开发需求是您必须自己做的决定。

必须在事务上下文中运行并且显式使用TransactionTemplate的应用程序代码类似于下一个示例。 作为应用程序开发人员,您可以编写TransactionCallback实现(通常表示为匿名内部类),其中包含您需要在事务上下文中运行的代码。 然后,您可以将自定义TransactionCallback的实例传递给TransactionTemplate上公开的execute(…)方法。 以下示例显示了如何执行此操作:

public class SimpleService implements Service {

    // single TransactionTemplate shared amongst all methods in this instance
    private final TransactionTemplate transactionTemplate;

    // use constructor-injection to supply the PlatformTransactionManager
    public SimpleService(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }

    public Object someServiceMethod() {
        return transactionTemplate.execute(new TransactionCallback() {
            // the code in this method runs in a transactional context
            public Object doInTransaction(TransactionStatus status) {
                updateOperation1();
                return resultOfUpdateOperation2();
            }
        });
    }
}

如果没有返回值,则可以将便捷TransactionCallbackWithoutResult类与匿名类一起使用,如下所示:

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

回调中的代码可以通过调用setRollbackOnly()提供的TransactionStatus对象上的方法来回滚事务 ,如下所示:

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

    protected void doInTransactionWithoutResult(TransactionStatus status) {
        try {
            updateOperation1();
            updateOperation2();
        } catch (SomeBusinessException ex) {
            status.setRollbackOnly();
        }
    }
});

指定事务设置

您可以以编程方式或配置方式在TransactionTemplate上指定事务设置(例如传播模式,隔离级别,超时等)。 默认情况下,TransactionTemplate实例具有默认的事务设置。 以下示例显示了针对特定TransactionTemplate的事务设置的编程自定义:

public class SimpleService implements Service {

    private final TransactionTemplate transactionTemplate;

    public SimpleService(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);

        // the transaction settings can be set here explicitly if so desired
        this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
        this.transactionTemplate.setTimeout(30); // 30 seconds
        // and so forth...
    }
}

以下示例TransactionTemplate通过使用Spring XML配置定义了具有一些自定义事务设置的:

<bean id="sharedTransactionTemplate"
        class="org.springframework.transaction.support.TransactionTemplate">
    <property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/>
    <property name="timeout" value="30"/>
</bean>

然后,您可以sharedTransactionTemplate 根据需要将服务注入到尽可能多的服务中。

最后,TransactionTemplate类的实例是线程安全的,因为这些实例不维护任何对话状态。 但是,TransactionTemplate实例确实会维护配置状态。 因此,尽管许多类可以共享一个TransactionTemplate实例,但是如果一个类需要使用具有不同设置(例如,不同的隔离级别)的TransactionTemplate,则需要创建两个不同的TransactionTemplate实例。

1.5.2。使用TransactionOperator

TransactionOperator遵循类似于其他反应式操作符的操作符设计。 它使用一种回调方法(使应用程序代码不必进行样板获取和释放事务性资源),并生成意向驱动的代码,因为您的代码仅专注于您要执行的操作。

如以下示例所示,使用TransactionOperator绝对链接可将您与Spring的事务基础结构和API结合使用。程序化事务管理是否适合您的开发需求是您必须自己做的决定。
必须在事务上下文中运行并且显式使用以下TransactionOperator类似的应用程序代码:

public class SimpleService implements Service {

    // single TransactionOperator shared amongst all methods in this instance
    private final TransactionalOperator transactionalOperator;

    // use constructor-injection to supply the ReactiveTransactionManager
    public SimpleService(ReactiveTransactionManager transactionManager) {
        this.transactionOperator = TransactionalOperator.create(transactionManager);
    }

    public Mono<Object> someServiceMethod() {

        // the code in this method runs in a transactional context

        Mono<Object> update = updateOperation1();

        return update.then(resultOfUpdateOperation2).as(transactionalOperator::transactional);
    }
}

TransactionalOperator 可以以两种方式使用:

  1. 使用Project Reactor类型的操作符样式(mono.as(transactionalOperator :: transactional))

2 其他情况的回调样式(transactionalOperator.execute(TransactionCallback))

回调中的代码可以通过调用setRollbackOnly() 提供的ReactiveTransaction对象上的方法来回滚事务,如下所示:

transactionalOperator.execute(new TransactionCallback<>() {

    public Mono<Object> doInTransaction(ReactiveTransaction status) {
        return updateOperation1().then(updateOperation2)
                    .doOnError(SomeBusinessException.class, e -> status.setRollbackOnly());
        }
    }
});

取消信号

在反应流中,Subscriber 可以取消其Subscription并停止其Publisher。 Project Reactor以及其他库(例如next(),take(long),timeout(Duration)和其他库)中的操作员都可以发出取消操作。 没有办法知道取消的原因,无论是由于错误还是仅仅是出于进一步消费的兴趣,并且在5.2版中,TransactionalOperator默认在取消时提交事务。 在5.3版中,此行为将更改,并且取消交易会回滚,以创建可靠的确定性结果。 因此,重要的是要考虑事务Publisher下游使用的运算符。 特别是在Flux或其他多值发布者的情况下,必须使用全部输出以使交易完成。

指定事务设置

您可以为TransactionalOperator指定事务设置(例如传播模式,隔离级别,超时等)。 默认情况下,TransactionalOperator实例具有默认的事务设置。 以下示例显示了针对特定TransactionalOperator的事务设置的自定义:

public class SimpleService implements Service {

    private final TransactionalOperator transactionalOperator;

    public SimpleService(ReactiveTransactionManager transactionManager) {
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();

        // the transaction settings can be set here explicitly if so desired
        definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
        definition.setTimeout(30); // 30 seconds
        // and so forth...

        this.transactionalOperator = TransactionalOperator.create(transactionManager, definition);
    }
}

1.5.3。使用TransactionManager

以下各节说明命令式和反应式事务管理器的程序用法。

使用 PlatformTransactionManager

对于命令性事务,可以直接使用org.springframework.transaction.PlatformTransactionManager来管理事务。 为此,请通过bean引用将您使用的PlatformTransactionManager的实现传递给bean。 然后,通过使用TransactionDefinition和TransactionStatus对象,可以启动事务,回滚和提交。 以下示例显示了如何执行此操作:

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can be done only programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);
try {
    // put your business logic here
}
catch (MyException ex) {
    txManager.rollback(status);
    throw ex;
}
txManager.commit(status);

使用 ReactiveTransactionManager

使用被动事务时,可以直接使用org.springframework.transaction.ReactiveTransactionManager来管理事务。 为此,请通过bean引用将您使用的ReactiveTransactionManager的实现传递给bean。 然后,通过使用TransactionDefinition和ReactiveTransaction对象,您可以启动事务,回滚和提交。 以下示例显示了如何执行此操作:

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can be done only programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

Mono<ReactiveTransaction> reactiveTx = txManager.getReactiveTransaction(def);

reactiveTx.flatMap(status -> {

    Mono<Object> tx = ...; // put your business logic here

    return tx.then(txManager.commit(status))
            .onErrorResume(ex -> txManager.rollback(status).then(Mono.error(ex)));
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值