此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

程序化事务管理

Spring Framework 提供了两种编程事务管理方法,通过使用:spring-doc.cadn.net.cn

Spring 团队一般建议将TransactionTemplate用于程序化 命令式流中的事务管理,以及TransactionalOperator用于响应式代码。 第二种方法类似于使用 JTAUserTransactionAPI,尽管例外 处理不那么麻烦。spring-doc.cadn.net.cn

使用TransactionTemplate

TransactionTemplate采用与其他 Spring 模板相同的方法,例如 这JdbcTemplate.它使用回调方法(使应用程序代码不必 进行样板采购并发布事务资源)并导致 意图驱动的代码,因为您的代码仅关注什么 你想做。spring-doc.cadn.net.cn

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

必须在事务上下文中运行并显式使用TransactionTemplate类似于下一个示例。您作为应用程序 developer,可以编写一个TransactionCallback实现(通常表示为 匿名内部类),其中包含您需要在 交易。然后,您可以传递自定义的实例TransactionCallbackexecute(..)TransactionTemplate.以下示例显示了如何执行此作:spring-doc.cadn.net.cn

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();
			}
		});
	}
}
// use constructor-injection to supply the PlatformTransactionManager
class SimpleService(transactionManager: PlatformTransactionManager) : Service {

	// single TransactionTemplate shared amongst all methods in this instance
	private val transactionTemplate = TransactionTemplate(transactionManager)

	fun someServiceMethod() = transactionTemplate.execute<Any?> {
		updateOperation1()
		resultOfUpdateOperation2()
	}
}

如果没有返回值,可以使用方便的TransactionCallbackWithoutResult类 使用匿名类,如下所示:spring-doc.cadn.net.cn

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

回调中的代码可以通过调用setRollbackOnly()提供的方法TransactionStatus对象,如下所示:spring-doc.cadn.net.cn

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

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

	override fun doInTransactionWithoutResult(status: TransactionStatus) {
		try {
			updateOperation1()
			updateOperation2()
		} catch (ex: SomeBusinessException) {
			status.setRollbackOnly()
		}
	}
})

指定事务设置

您可以指定事务设置(例如传播模式、隔离级别、 超时,依此类推)在TransactionTemplate以编程方式或以 配置。默认情况下,TransactionTemplate实例具有默认的事务设置。这 以下示例显示了事务设置的编程自定义 一个特定的TransactionTemplate:spring-doc.cadn.net.cn

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...
	}
}
class SimpleService(transactionManager: PlatformTransactionManager) : Service {

	private val transactionTemplate = TransactionTemplate(transactionManager).apply {
		// the transaction settings can be set here explicitly if so desired
		isolationLevel = TransactionDefinition.ISOLATION_READ_UNCOMMITTED
		timeout = 30 // 30 seconds
		// and so forth...
	}
}

以下示例定义了TransactionTemplate使用一些自定义事务 使用 Spring XML 配置进行设置:spring-doc.cadn.net.cn

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

然后,您可以注入sharedTransactionTemplate转换为所需的服务。spring-doc.cadn.net.cn

最后,的实例TransactionTemplate类是线程安全的,在这种情况下 不要保持任何对话状态。TransactionTemplate然而,实例确实如此, 维护配置状态。因此,虽然多个类可以共享一个实例 的TransactionTemplate,如果类需要使用TransactionTemplate跟 不同的设置(例如,不同的隔离级别),您需要创建 两个不同的TransactionTemplate实例。spring-doc.cadn.net.cn

使用TransactionalOperator

TransactionalOperator遵循与其他响应式类似的运算符设计 运营商。它使用回调方法(使应用程序代码不必执行 样板获取和释放事务资源),并生成代码 意图驱动,因为您的代码只关注您想要做的事情。spring-doc.cadn.net.cn

如下例所示,使用TransactionalOperator绝对 将您与 Spring 的事务基础设施和 API 相结合。是否为程序化 事务管理是否适合您的开发需求是您的决定 让自己。

必须在事务上下文中运行并显式使用 这TransactionalOperator类似于下一个示例:spring-doc.cadn.net.cn

public class SimpleService implements Service {

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

	// use constructor-injection to supply the ReactiveTransactionManager
	public SimpleService(ReactiveTransactionManager transactionManager) {
		this.transactionalOperator = 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);
	}
}
// use constructor-injection to supply the ReactiveTransactionManager
class SimpleService(transactionManager: ReactiveTransactionManager) : Service {

	// single TransactionalOperator shared amongst all methods in this instance
	private val transactionalOperator = TransactionalOperator.create(transactionManager)

	suspend fun someServiceMethod() = transactionalOperator.executeAndAwait<Any?> {
		updateOperation1()
		resultOfUpdateOperation2()
	}
}

TransactionalOperator可以通过两种方式使用:spring-doc.cadn.net.cn

  • 使用项目反应堆类型的运算符样式 (mono.as(transactionalOperator::transactional))spring-doc.cadn.net.cn

  • 回调样式适用于所有其他情况 (transactionalOperator.execute(TransactionCallback<T>))spring-doc.cadn.net.cn

回调中的代码可以通过调用setRollbackOnly()提供的方法ReactiveTransaction对象,如下所示:spring-doc.cadn.net.cn

transactionalOperator.execute(new TransactionCallback<>() {

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

	override fun doInTransactionWithoutResult(status: ReactiveTransaction) {
		updateOperation1().then(updateOperation2)
					.doOnError(SomeBusinessException.class, e -> status.setRollbackOnly())
	}
})

取消信号

在响应式流中,Subscriber可以取消其Subscription并停止其Publisher.Project Reactor 中的运算符,以及其他库中的运算符,例如next(),take(long),timeout(Duration),其他人可以发出取消。没有办法 了解取消的原因,是由于错误还是仅仅缺少 兴趣进一步消费。自 5.3 版以来,取消信号会导致回滚。 因此,重要的是要考虑事务下游使用的运算符Publisher.特别是在Flux或其他多值Publisher, 必须使用完整输出才能完成事务。spring-doc.cadn.net.cn

指定事务设置

您可以为TransactionalOperator. 默认情况下,TransactionalOperator实例具有默认事务设置。 这 以下示例显示了特定事务设置的自定义TransactionalOperator:spring-doc.cadn.net.cn

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);
	}
}
class SimpleService(transactionManager: ReactiveTransactionManager) : Service {

	private val definition = DefaultTransactionDefinition().apply {
		// the transaction settings can be set here explicitly if so desired
		isolationLevel = TransactionDefinition.ISOLATION_READ_UNCOMMITTED
		timeout = 30 // 30 seconds
		// and so forth...
	}
	private val transactionalOperator = TransactionalOperator(transactionManager, definition)
}

使用TransactionManager

以下各节将说明命令式事务和响应式事务的编程用法 经理。spring-doc.cadn.net.cn

使用PlatformTransactionManager

对于命令式事务,您可以使用org.springframework.transaction.PlatformTransactionManager直接管理您的 交易。 为此,请通过PlatformTransactionManager你 通过 bean 引用对 bean 使用。然后,通过使用TransactionDefinitionTransactionStatus对象,您可以启动事务、回滚和提交。 这 以下示例显示了如何执行此作:spring-doc.cadn.net.cn

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);
val def = DefaultTransactionDefinition()
// explicitly setting the transaction name is something that can be done only programmatically
def.setName("SomeTxName")
def.propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRED

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

txManager.commit(status)

使用ReactiveTransactionManager

处理响应式事务时,可以使用org.springframework.transaction.ReactiveTransactionManager直接管理您的 交易。 为此,请通过ReactiveTransactionManager你 通过 bean 引用对 bean 使用。然后,通过使用TransactionDefinitionReactiveTransaction对象,您可以启动事务、回滚和提交。 这 以下示例显示了如何执行此作:spring-doc.cadn.net.cn

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)));
});
val def = DefaultTransactionDefinition()
// explicitly setting the transaction name is something that can be done only programmatically
def.setName("SomeTxName")
def.propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRED

val reactiveTx = txManager.getReactiveTransaction(def)
reactiveTx.flatMap { status ->

	val tx = ... // put your business logic here

	tx.then(txManager.commit(status))
			.onErrorResume { ex -> txManager.rollback(status).then(Mono.error(ex)) }
}