此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
了解 Spring Framework 事务抽象
Spring 事务抽象的关键是事务策略的概念。一个
交易策略由TransactionManager
,特别是org.springframework.transaction.PlatformTransactionManager
命令式接口
事务管理和org.springframework.transaction.ReactiveTransactionManager
反应式接口
事务管理。下面的清单显示了PlatformTransactionManager
应用程序接口:
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
是一个接口,它可以很容易地被 mock 或 stubbed 为
必要。它与查找策略(如 JNDI)无关。PlatformTransactionManager
实现的定义与任何其他对象(或 bean)一样
在 Spring Framework IoC 容器中。仅此一项优势就使 Spring Framework
transactions 是一个有价值的抽象,即使您使用 JTA 也是如此。您可以测试
事务性代码比直接使用 JTA 要容易得多。
同样,为了与 Spring 的理念保持一致,TransactionException
那可以被抛出
由任何PlatformTransactionManager
interface 的方法未选中(即
is,它扩展了java.lang.RuntimeException
类)。交易基础设施
失败几乎总是致命的。在应用程序代码实际上可以
从事务失败中恢复,应用程序开发人员仍然可以选择捕获
和手柄TransactionException
.突出的一点是开发人员不是被迫这样做的。
这getTransaction(..)
method 返回一个TransactionStatus
对象,具体取决于TransactionDefinition
参数。返回的TransactionStatus
可能表示
新交易,也可以表示现有交易(如果是匹配的交易)
存在于当前调用堆栈中。后一种情况的含义是,与
Jakarta EE 事务上下文,一个TransactionStatus
与
执行。
Spring 还为响应式应用程序提供了一个事务管理抽象,这些应用程序
使用反应式类型或 Kotlin 协程。下面的清单显示了
交易策略定义org.springframework.transaction.ReactiveTransactionManager
:
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
是一个界面,它可以轻松
根据需要被 mock 或 stubbed 进行。
这TransactionDefinition
interface 指定:
-
传播:通常,事务范围内的所有代码都在 那笔交易。但是,如果 当事务上下文已存在时,将运行 transactional 方法。为 example,代码可以继续在现有事务中运行(常见情况),或者 可以暂停现有事务并创建新事务。Spring 提供 EJB CMT 中熟悉的所有事务传播选项。阅读 关于 Spring 中事务传播的语义,请参见事务传播。
-
隔离:此事务与其他事务的工作隔离的程度 交易。例如,此事务能否看到来自其他 交易?
-
Timeout:此事务在超时并自动回滚之前运行的时间 通过底层事务基础设施。
-
Read-only 状态:当您的代码读取但 不修改数据。只读事务在某些 的情况下,例如当您使用 Hibernate 时。
这些设置反映了标准的事务概念。如有必要,请参阅 参考资料 讨论事务隔离级别和其他核心事务概念。 理解这些概念对于使用 Spring Framework 或任何 事务管理解决方案。
这TransactionStatus
接口为事务代码提供了一种简单的方法:
控制事务执行并查询事务状态。概念应该是
熟悉,因为它们对所有事务 API 都是通用的。下面的清单显示了TransactionStatus
接口:
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
@Override
boolean isNewTransaction();
boolean hasSavepoint();
@Override
void setRollbackOnly();
@Override
boolean isRollbackOnly();
void flush();
@Override
boolean isCompleted();
}
无论您在
Spring,定义正确的TransactionManager
实施是绝对必要的。
通常通过依赖项注入来定义此实现。
TransactionManager
实现通常需要了解
他们使用的 JDBC、JTA、Hibernate 等。以下示例显示了如何
定义本地PlatformTransactionManager
implementation (在本例中,使用 plain
JDBC。
您可以定义 JDBCDataSource
通过创建类似于以下内容的 Bean:
<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>
相关的PlatformTransactionManager
bean 定义具有对DataSource
定义。它应类似于以下示例:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
如果您在 Jakarta EE 容器中使用 JTA,那么您使用容器DataSource
获得
通过 JNDI 与 Spring 的JtaTransactionManager
.以下示例
显示了 JTA 和 JNDI 查找版本的外观:
<?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
(或任何其他
特定资源),因为它使用容器的全局事务管理
基础设施。
前面的dataSource Bean 使用<jndi-lookup/> 标记
从jee Namespace。有关更多信息,请参阅 JEE 架构。 |
如果您使用 JTA,则无论如何,您的事务管理器定义看起来都应该相同 您使用的数据访问技术,无论是 JDBC、Hibernate JPA 还是任何其他受支持的 科技。这是因为 JTA 事务是全局事务,而 可以登记任何事务性资源。 |
在所有 Spring 事务设置中,应用程序代码不需要更改。您可以更改 如何仅通过更改配置来管理事务,即使该更改意味着 从本地交易转向全球交易,反之亦然。
Hibernate 事务设置
您还可以轻松使用 Hibernate 本地事务,如以下示例所示。
在这种情况下,您需要定义一个 HibernateLocalSessionFactoryBean
,其中您的
应用程序代码可用于获取 HibernateSession
实例。
这DataSource
bean 定义类似于前面显示的本地 JDBC 示例
因此,以下示例中未显示 。
如果DataSource (由任何非 JTA 事务管理器使用)通过
JNDI 并由 Jakarta EE 容器管理,则它应该是非事务性的,因为
Spring Framework(而不是 Jakarta EE 容器)管理事务。 |
这txManager
bean 的HibernateTransactionManager
类型。在
与DataSourceTransactionManager
需要引用DataSource
这HibernateTransactionManager
需要引用SessionFactory
.以下内容
example 声明sessionFactory
和txManager
豆:
<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 事务,则应使用
相同JtaTransactionManager
如前面的 JDBC 的 JTA 示例所示,如下所示
示例显示。此外,建议通过 Hibernate 的 JTA
Transaction Coordinator 以及可能的 Connection Release Mode 配置:
<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"/>
或者,您也可以将JtaTransactionManager
放入您的LocalSessionFactoryBean
用于强制实施相同的默认值:
<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"/>