Spring 事务抽象的关键是事务策略的概念。一个 事务策略由 定义,具体来说是命令式 事务管理和反应式接口 事务管理。以下列表显示了 API 的定义:TransactionManagerorg.springframework.transaction.PlatformTransactionManagerorg.springframework.transaction.ReactiveTransactionManagerPlatformTransactionManagerSpring中文文档

public interface PlatformTransactionManager extends TransactionManager {

	TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

	void commit(TransactionStatus status) throws TransactionException;

	void rollback(TransactionStatus status) throws TransactionException;
}

这主要是一个服务提供程序接口 (SPI),尽管您可以从应用程序代码中以编程方式使用它。因为是一个接口,所以它可以很容易地被嘲笑或存根为 必要。它与查找策略(如 JNDI)无关。 实现的定义与任何其他对象(或 Bean)类似 在 Spring Framework IoC 容器中。仅此一项优势就使 Spring Framework 事务是一个有价值的抽象,即使你使用JTA也是如此。你可以测试 事务代码比直接使用 JTA 要容易得多。PlatformTransactionManagerPlatformTransactionManagerSpring中文文档

同样,根据 Spring 的哲学,可以抛出的 通过接口的任何方法都未选中(该 是,它扩展了类)。交易基础设施 失败几乎总是致命的。在极少数情况下,应用程序代码实际上可以 从事务失败中恢复,应用程序开发人员仍然可以选择捕获 和句柄 .突出的一点是,开发人员不会被迫这样做。TransactionExceptionPlatformTransactionManagerjava.lang.RuntimeExceptionTransactionExceptionSpring中文文档

该方法返回一个对象,具体取决于参数。返回的可能表示 新交易或可以表示现有交易,如果交易匹配 存在于当前调用堆栈中。后一种情况的含义是,与 Jakarta EE 事务上下文中,a 与 执行。getTransaction(..)TransactionStatusTransactionDefinitionTransactionStatusTransactionStatusSpring中文文档

从 Spring Framework 5.2 开始,Spring 还为 使用反应式类型或 Kotlin 协程的响应式应用程序。以下 列表显示了由以下定义的交易策略:org.springframework.transaction.ReactiveTransactionManagerSpring中文文档

public interface ReactiveTransactionManager extends TransactionManager {

	Mono<ReactiveTransaction> getReactiveTransaction(TransactionDefinition definition) throws TransactionException;

	Mono<Void> commit(ReactiveTransaction status) throws TransactionException;

	Mono<Void> rollback(ReactiveTransaction status) throws TransactionException;
}

反应式事务管理器主要是一个服务提供商接口(SPI), 尽管您可以从您的 应用程序代码。因为是一个接口,所以可以很容易地 必要时嘲笑或存根。ReactiveTransactionManagerSpring中文文档

该接口指定:TransactionDefinitionSpring中文文档

  • 传播:通常,事务范围内的所有代码都在 该交易。但是,如果出现以下情况,您可以指定行为 当事务上下文已存在时,将运行事务方法。为 例如,代码可以在现有事务中继续运行(常见情况),或者 可以暂停现有事务并创建新事务。Spring 提供 EJB CMT 中熟悉的所有事务传播选项。要阅读 关于 Spring 中事务传播的语义,请参阅事务传播Spring中文文档

  • 隔离:此事务与其他事务的工作隔离的程度 交易。例如,此事务是否可以查看来自其他事务的未提交写入 交易?Spring中文文档

  • 超时:此事务在超时并自动回滚之前运行的时间 由底层事务基础设施提供。Spring中文文档

  • 只读状态:当代码读取但 不修改数据。在某些情况下,只读事务可能是一个有用的优化 情况,例如使用 Hibernate 时。Spring中文文档

这些设置反映了标准的事务概念。如有必要,请参阅参考资料 讨论事务隔离级别和其他核心事务概念。 理解这些概念对于使用 Spring 框架或任何 事务管理解决方案。Spring中文文档

该接口为事务代码提供了一种简单的方法 控制事务执行并查询事务状态。这些概念应该是 熟悉,因为它们是所有事务 API 通用的。以下列表显示了该接口:TransactionStatusTransactionStatusSpring中文文档

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

	@Override
	boolean isNewTransaction();

	boolean hasSavepoint();

	@Override
	void setRollbackOnly();

	@Override
	boolean isRollbackOnly();

	void flush();

	@Override
	boolean isCompleted();
}

无论您选择声明式还是程序化事务管理,在 Spring,定义正确的实现是绝对必要的。 通常通过依赖关系注入来定义此实现。TransactionManagerSpring中文文档

TransactionManager实现通常需要了解 它们的工作方式:JDBC、JTA、Hibernate 等。以下示例演示如何执行以下操作 定义一个本地实现(在本例中,使用 plain JDBC.)PlatformTransactionManagerSpring中文文档

您可以通过创建类似于以下内容的 Bean 来定义 JDBC:DataSourceSpring中文文档

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
	<property name="driverClassName" value="${jdbc.driverClassName}" />
	<property name="url" value="${jdbc.url}" />
	<property name="username" value="${jdbc.username}" />
	<property name="password" value="${jdbc.password}" />
</bean>

然后,相关的 Bean 定义具有对定义的引用。它应类似于以下示例:PlatformTransactionManagerDataSourceSpring中文文档

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

如果你在Jakarta EE容器中使用JTA,那么你使用一个容器,获得 通过 JNDI,与 Spring 的 .以下示例 显示了 JTA 和 JNDI 查找版本的样子:DataSourceJtaTransactionManagerSpring中文文档

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/jee
		https://www.springframework.org/schema/jee/spring-jee.xsd">

	<jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>

	<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

	<!-- other <bean/> definitions here -->

</beans>

不需要知道 (或任何其他 特定资源),因为它使用容器的全局事务管理 基础设施。JtaTransactionManagerDataSourceSpring中文文档

Bean 的上述定义使用标记 从命名空间。有关详细信息,请参阅 JEE 架构dataSource<jndi-lookup/>jee
如果使用 JTA,那么事务管理器定义应该看起来相同,无论如何 您使用的数据访问技术,无论是 JDBC、Hibernate JPA 还是任何其他支持的技术 科技。这是因为 JTA 事务是全局事务,这 可以登记任何事务性资源。

在所有 Spring 事务设置中,应用程序代码不需要更改。您可以更改 如何仅通过更改配置来管理事务,即使该更改意味着 从本地事务转移到全局事务,反之亦然。Spring中文文档

Bean 的上述定义使用标记 从命名空间。有关详细信息,请参阅 JEE 架构dataSource<jndi-lookup/>jee
如果使用 JTA,那么事务管理器定义应该看起来相同,无论如何 您使用的数据访问技术,无论是 JDBC、Hibernate JPA 还是任何其他支持的技术 科技。这是因为 JTA 事务是全局事务,这 可以登记任何事务性资源。

休眠事务设置

您还可以轻松使用 Hibernate 本地事务,如以下示例所示。 在这种情况下,您需要定义一个 Hibernate ,其中 应用程序代码可用于获取 Hibernate 实例。LocalSessionFactoryBeanSessionSpring中文文档

Bean 定义类似于前面所示的本地 JDBC 示例 因此,以下示例中未显示。DataSourceSpring中文文档

如果 (由任何非 JTA 事务管理器使用) 被查找 JNDI 并由 Jakarta EE 容器管理,它应该是非事务性的,因为 Spring Framework(而不是 Jakarta EE 容器)管理事务。DataSource

在本例中,bean 属于 type。在 与需要对 的引用一样,需要对 的引用。以下 示例声明和 Bean:txManagerHibernateTransactionManagerDataSourceTransactionManagerDataSourceHibernateTransactionManagerSessionFactorysessionFactorytxManagerSpring中文文档

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	<property name="dataSource" ref="dataSource"/>
	<property name="mappingResources">
		<list>
			<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
		</list>
	</property>
	<property name="hibernateProperties">
		<value>
			hibernate.dialect=${hibernate.dialect}
		</value>
	</property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory"/>
</bean>

如果使用 Hibernate 和 Jakarta EE 容器管理的 JTA 事务,则应使用 与前面的 JDBC JTA 示例相同,如下所示 示例显示。此外,建议通过其 事务协调器,可能还有它的连接释放模式配置:JtaTransactionManagerSpring中文文档

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	<property name="dataSource" ref="dataSource"/>
	<property name="mappingResources">
		<list>
			<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
		</list>
	</property>
	<property name="hibernateProperties">
		<value>
			hibernate.dialect=${hibernate.dialect}
			hibernate.transaction.coordinator_class=jta
			hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT
		</value>
	</property>
</bean>

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

或者,您可以将 传递给 your 以强制执行相同的默认值:JtaTransactionManagerLocalSessionFactoryBeanSpring中文文档

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	<property name="dataSource" ref="dataSource"/>
	<property name="mappingResources">
		<list>
			<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
		</list>
	</property>
	<property name="hibernateProperties">
		<value>
			hibernate.dialect=${hibernate.dialect}
		</value>
	</property>
	<property name="jtaTransactionManager" ref="txManager"/>
</bean>

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
如果 (由任何非 JTA 事务管理器使用) 被查找 JNDI 并由 Jakarta EE 容器管理,它应该是非事务性的,因为 Spring Framework(而不是 Jakarta EE 容器)管理事务。DataSource