3.4. 使用 Spring Boot 事务客户端
Spring Framework(和 Spring Boot)主要目标之一是使 JavaEE API 更易于使用。所有主要的 JavaEE vanilla API 在 Spring Framework(Spring Boot)中都有它们的一部分。这些不是给定 API 的替代方案或替代,而是打包程序会添加更多配置选项或更一致的用法,例如,处理异常。
下表将给定的 JavaEE API 与其 Spring 相关的接口匹配:
JavaEE API | Spring 工具程序 | 配置使用 |
---|---|---|
JDBC |
|
|
JMS |
|
|
JTA |
|
|
JdbcTemplate
和 JmsTemplate
分别使用 javax.sql.DataSource
和 javax.jms.ConnectionFactory
。但 TransactionTemplate
使用 PlatformTransactionManager
的 Spring 接口。在这里,Spring 不只是 改进 JavaEE,而是将 JavaEE 客户端 API 替换为其自身的。
Spring 将 javax.transaction.UserTransaction
视为一个对于实际情况来说非常简单的接口。另外,因为 javax.transaction.UserTransaction
无法区分本地、单一资源事务和全球多资源事务,因此 org.springframework.transaction.transaction.PlatformTransactionManager
赋予开发人员更具自由度。
以下是 Spring Boot 的规范 API 用法:
// Create or get from ApplicationContext or injected with @Inject/@Autowired. JmsTemplate jms = new JmsTemplate(...); JdbcTemplate jdbc = new JdbcTemplate(...); TransactionTemplate tx = new TransactionTemplate(...); tx.execute((status) -> { // Perform JMS operations within transaction. jms.execute((SessionCallback<Object>)(session) -> { // Perform operations on JMS session return ...; }); // Perform JDBC operations within transaction. jdbc.execute((ConnectionCallback<Object>)(connection) -> { // Perform operations on JDBC connection. return ...; }); return ...; });
在上例中,所有三种类型的 模板都 只是实例化,但它们也可以从 Spring 应用的 Context
获取,或使用 @Autowired
注解注入。
3.4.1. 使用 Spring PlatformTransactionManager 接口
如前文中所述,javax.transaction.UserTransaction
通常来自 JavaEE 应用中的 JNDI。但是 Spring 会为很多场景提供这个界面的显式实现。您不需要完整的 JTA 情景,有时应用只需要访问单个资源,如 JDBC。
通常, org.springframework.transaction.PlatformTransactionManager
是 Spring 事务客户端 API,提供经典的事务客户端操作: 开始
、提交和
回滚
。换句话说,此接口提供了在运行时控制事务的基本方法。
任何事务系统的另一个关键方面是实施事务资源的 API。但是,事务资源通常由底层数据库实施,因此交易编程的此类方面很少是应用程序编程的关注。
3.4.1.1. PlatformTransactionManager 接口的定义
public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }
3.4.1.2. 关于 TransactionDefinition 接口
您可以使用 TransactionDefinition
接口指定新创建的事务的特征。您可以指定新事务的隔离级别和传播策略。详情请查看 第 9.4 节 “事务传播策略”。
3.4.1.3. TransactionStatus 接口的定义
您可以使用 TransactionStatus
接口来检查当前事务的状态,即与当前线程关联的事务,并为当前线程标记当前的事务进行回滚。这是接口定义:
public interface TransactionStatus extends SavepointManager, Flushable { boolean isNewTransaction(); boolean hasSavepoint(); void setRollbackOnly(); boolean isRollbackOnly(); void flush(); boolean isCompleted(); }
3.4.1.4. 由 PlatformTransactionManager 接口定义的方法
PlatformTransactionManager
接口定义以下方法:
- getTransaction()
-
创建一个新的事务,并通过传递一个
定义新事务
的特性来将其与当前线程相关联。这与许多其他事务客户端 API 的 start()
方法类似。 - commit()
- 提交当前的事务,这样对注册的资源的所有待处理的更改都是永久的。
- rollback()
- 回滚当前的事务,这会撤消对注册的资源的所有待处理更改。
3.4.2. 使用事务管理器的步骤
通常,您不会直接使用 PlatformTransactionManager
接口。在 Apache Camel 中,您通常使用事务管理器,如下所示:
- 创建事务管理器实例。Spring 中有几种不同的实现,请参阅 第 3.4 节 “使用 Spring Boot 事务客户端”。
-
将事务管理器实例传递到 Apache Camel 组件或路由中的
transacted()
DSL 命令。然后,事务组件或transacted()
命令负责分离事务。详情请查看 第 9 章 编写使用事务的 Camel 应用程序。
3.4.3. 关于 Spring PlatformTransactionManager 实现
本节概述了 Spring Framework 提供的事务管理器实现。该实施分为两类:本地事务管理器和全球交易经理。
从 Camel 开始:
-
camel-jms
组件使用的 org.apache.camel.component.JmsConfigurationorg.springframework.transaction.transaction.PlatformTransactionManager
接口的实例。 -
org.apache.camel.component.sql.SqlComponent
在内部使用org.springframework.jdbc.core.JdbcTemplate
类,此 JDBC 模板也与org.springframework.transaction.transaction.transaction.PlatformTransactionManager
集成。
如您所见,您必须 有一些 实现这个接口。根据具体情况,您可以配置所需的平台事务管理器。
3.4.3.1. Local PlatformTransactionManager 实现
以下列表总结了 Spring Framework 提供的本地事务管理器实现。这些事务管理器只支持单个资源。
- org.springframework.jms.connection.JmsTransactionManager
- 此事务管理器实施能够管理 单个 JMS 资源。您可以连接到任意数量的队列或主题,但前提是它们属于同一基础 JMS 消息传递产品实例。此外,您也无法在事务中列出其他类型的资源。
- org.springframework.jdbc.datasource.DataSourceTransactionManager
- 此事务管理器实施能够管理 单个 JDBC 数据库资源。您可以更新任意数量的不同数据库表,但前提是 它们属于同一基础数据库实例。
- org.springframework.orm.jpa.JpaTransactionManager
- 此事务管理器实施能够管理 Java Persistence API(JPA)资源。但是,无法同时将其他类型的资源列于事务中。
- org.springframework.orm.hibernate5.HibernateTransactionManager
- 此事务管理器实施能够管理 Hibernate 资源。但是,无法同时将其他类型的资源列于事务中。此外,JPA API 比原生 Hibernate API 更首选。
另外,还有其他不常使用的、不常使用的、平台 可靠性管理器的
实现。
3.4.3.2. Global PlatformTransactionManager 实现
Spring Framework 提供了一个全局事务管理器实施,用于在 OSGi 运行时使用。org.springframework.transaction.jta.JtaTransactionManager
支持对事务中的多个资源的操作。这个事务管理器支持 XA 事务 API,并可在事务中放入多个资源。要使用此事务管理器,您必须将应用程序部署到 OSGi 容器或 JavaEE 服务器中。
虽然 PlatformTransactionManager
的单资源实施是实际的 实现,但JtaTransactionManager
更加适用于标准 javax.transaction.TransactionManager
的实际实现。
因此,您可以在可以访问的环境中运行 PlatformTransactionManager
的 JtaTransactionManager
实施(通过 JNDI 或 CDI)已经配置了 javax.transaction.TransactionManager
且通常是 javax.transaction.UserTransaction
.通常,这两个接口都由单个对象/服务实施。
以下是配置/使用 JtaTransactionManager
的示例:
InitialContext context = new InitialContext(); UserTransaction ut = (UserTransaction) context.lookup("java:comp/UserTransaction"); TransactionManager tm = (TransactionManager) context.lookup("java:/TransactionManager"); JtaTransactionManager jta = new JtaTransactionManager(); jta.setUserTransaction(ut); jta.setTransactionManager(tm); TransactionTemplate jtaTx = new TransactionTemplate(jta); jtaTx.execute((status) -> { // Perform resource access in the context of global transaction. return ...; });
在上例中,JTA 对象(UserTransaction
和 TransactionManager
)的实际实例来自 JNDI。在 OSGi 中,它们也可以从 OSGi 服务注册表获得。