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