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

了解 Spring Framework 事务抽象

Spring 事务抽象的关键是事务策略的概念。一个 事务策略由TransactionManager,具体来说org.springframework.transaction.PlatformTransactionManager命令式接口 事务管理和org.springframework.transaction.ReactiveTransactionManager响应式接口 事务管理。以下列表显示了PlatformTransactionManager应用程序接口:spring-doc.cadn.net.cn

public interface PlatformTransactionManager extends TransactionManager {

	TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

	void commit(TransactionStatus status) throws TransactionException;

	void rollback(TransactionStatus status) throws TransactionException;
}

这主要是一个服务提供商接口 (SPI),尽管您可以从应用程序代码中以编程方式使用它。因为PlatformTransactionManager是一个接口,它可以很容易地被模拟或存根为 必要。它不与查找策略(如 JNDI)绑定。PlatformTransactionManager实现的定义与任何其他对象(或 bean)一样 在 Spring Framework IoC 容器中。仅此一项好处就使 Spring Framework 事务是一个有价值的抽象,即使您使用 JTA 也是如此。您可以测试 事务代码比直接使用 JTA 要容易得多。spring-doc.cadn.net.cn

同样,为了与 Spring 的理念保持一致,该TransactionException可以扔的 通过任何PlatformTransactionManager接口的方法未选中(即 是,它扩展了java.lang.RuntimeException类)。事务基础设施 失败几乎总是致命的。在极少数情况下,应用程序代码实际上可以 从事务失败中恢复,应用程序开发人员仍然可以选择捕获 和处理TransactionException.突出的一点是,开发人员不是被迫这样做的。spring-doc.cadn.net.cn

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

Spring 还为响应式应用程序提供了事务管理抽象,这些应用程序 使用响应式类型或 Kotlin 协程。以下列表显示了 事务策略定义为org.springframework.transaction.ReactiveTransactionManager:spring-doc.cadn.net.cn

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), 尽管您可以从 应用程序代码。因为ReactiveTransactionManager是一个接口,它可以轻松 必要时被嘲笑或砍伐。spring-doc.cadn.net.cn

TransactionDefinition接口指定:spring-doc.cadn.net.cn

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

  • 隔离:此事务与其他事务的工作隔离的程度 交易。例如,此事务是否可以查看来自其他事务的未提交写入 交易?spring-doc.cadn.net.cn

  • 超时:此事务在超时并自动回滚之前运行了多长时间 由底层交易基础设施。spring-doc.cadn.net.cn

  • 只读状态:当代码读取但 不修改数据。只读事务在某些方面可能是一种有用的优化 情况,例如当您使用 Hibernate 时。spring-doc.cadn.net.cn

这些设置反映了标准事务概念。如有必要,请参阅资源 讨论事务隔离级别和其他核心事务概念。 理解这些概念对于使用 Spring Framework 或任何 事务管理解决方案。spring-doc.cadn.net.cn

TransactionStatus接口为事务代码提供了一种简单的方法 控制事务执行并查询事务状态。概念应该是 熟悉,因为它们是所有事务 API 通用的。以下列表显示了TransactionStatus接口:spring-doc.cadn.net.cn

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

	@Override
	boolean isNewTransaction();

	boolean hasSavepoint();

	@Override
	void setRollbackOnly();

	@Override
	boolean isRollbackOnly();

	void flush();

	@Override
	boolean isCompleted();
}

无论您选择声明式还是编程式事务管理 弹簧,定义正确的TransactionManager实施是绝对必要的。 通常通过依赖项注入来定义此实现。spring-doc.cadn.net.cn

TransactionManager实现通常需要了解环境中的环境 它们工作:JDBC、JTA、Hibernate 等。以下示例演示了如何 定义本地PlatformTransactionManager实现(在本例中,使用 plain JDBC。spring-doc.cadn.net.cn

您可以定义 JDBCDataSource通过创建一个类似于以下内容的 bean:spring-doc.cadn.net.cn

<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>

相关PlatformTransactionManagerbean 定义则引用了DataSource定义。它应该类似于以下示例:spring-doc.cadn.net.cn

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

如果您在 Jakarta EE 容器中使用 JTA,则使用DataSource获得 通过 JNDI 与 Spring 的JtaTransactionManager.以下示例 显示了 JTA 和 JNDI 查找版本的外观:spring-doc.cadn.net.cn

<?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>

JtaTransactionManager不需要知道DataSource(或任何其他 特定资源),因为它使用容器的全局事务管理 基础设施。spring-doc.cadn.net.cn

前面的定义dataSourcebean 使用<jndi-lookup/>标记 从jeeNamespace。有关详细信息,请参阅 JEE 架构
如果您使用 JTA,则无论如何,您的事务管理器定义都应该看起来相同 您使用的数据访问技术,无论是 JDBC、Hibernate JPA 还是任何其他受支持的技术 科技。这是因为 JTA 事务是全局事务,而 可以征用任何事务资源。

在所有 Spring 事务设置中,应用程序代码不需要更改。您可以更改 如何仅通过更改配置来管理事务,即使该更改意味着 从本地交易转移到全球交易,反之亦然。spring-doc.cadn.net.cn

Hibernate 事务设置

您还可以轻松使用 Hibernate 本地事务,如以下示例所示。 在这种情况下,您需要定义一个 HibernateLocalSessionFactoryBean,您的 应用程序代码可用于获取 HibernateSession实例。spring-doc.cadn.net.cn

DataSourcebean 定义类似于前面显示的本地 JDBC 示例 因此,以下示例中未显示。spring-doc.cadn.net.cn

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

txManager在这种情况下,bean 是HibernateTransactionManager类型。在 与DataSourceTransactionManager需要引用DataSourceHibernateTransactionManager需要引用SessionFactory.以下内容 示例声明sessionFactorytxManager豆:spring-doc.cadn.net.cn

<bean id="sessionFactory" class="org.springframework.orm.jpa.hibernate.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.jpa.hibernate.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory"/>
</bean>

如果您使用 Hibernate 和 Jakarta EE 容器管理的 JTA 事务,则应使用 相同JtaTransactionManager如前面的 JDBC JTA 示例,如下所示 示例显示。此外,建议通过其 事务协调器,可能还有它的连接释放模式配置:spring-doc.cadn.net.cn

<bean id="sessionFactory" class="org.springframework.orm.jpa.hibernate.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"/>

或者,您可以将JtaTransactionManager进入您的LocalSessionFactoryBean用于强制执行相同的默认值:spring-doc.cadn.net.cn

<bean id="sessionFactory" class="org.springframework.orm.jpa.hibernate.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"/>