3.4. 使用 Spring Boot 事务客户端
Spring Framework (和 Spring Boot)的一个主要目标是使 QPC API 更易于使用。所有主要的 vanilla API 将其部分在 Spring 框架(Spring Boot)中。这些不是给定 API 的替代方案 或替换,而是添加更多配置选项或更一致的用法的打包程序,例如处理异常。
下表与 Spring 相关的接口匹配给定了>=< API:
JavaEE API | Spring utility | 配置为 |
---|---|---|
JDBC |
|
|
JMS |
|
|
JTA |
|
|
JdbcTemplate
和 JmsTemplate
分别直接使用 javax.sql.DataSource
和 javax.jms.ConnectionFactory
。但是 TransactionTemplate
使用 PlatformTransactionManager
的 Spring 接口。在这里,Spring 并不只是 改进 QPC,而是将 binutils 客户端 API 替换为自己的 API。
Spring 将 javax.transaction.UserTransaction
视为接口,对于真实情况来说非常简单。另外,因为 javax.transaction.UserTransaction
没有区分本地、单一资源事务和全局多资源事务,因此 org.springframework.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 的 ApplicationContext
获取,也可以使用 @Autowired
注解注入。
3.4.1. 使用 Spring PlatformTransactionManager 接口
如前文所述,javax.transaction.UserTransaction
通常从 QPC 应用中的 JNDI 获取。但是,Spring 为许多场景提供明确的这个接口实现。您不需要完整的 JTA 场景,有时应用程序只需要访问单个资源,如 JDBC。
通常,org.springframework.transaction.PlatformTransactionManager
是 Spring 事务客户端 API,它提供经典事务客户端操作: begin
、commit
和 rollback
。换句话说,这个接口提供了在运行时控制事务的基本方法。
任何事务系统的其他关键方面都是实施事务资源的 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. 平台TransactionManager 接口定义的方法
PlatformTransactionManager
接口定义以下方法:
- getTransaction()
-
创建新的事务,并通过传递定义新事务的特征的
TransactionDefinition
对象来将其与当前的线程相关联。这与许多其他事务客户端 API 的begin ()
方法类似。 - 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.PlatformTransactionManager
接口的实例。 -
org.apache.camel.component.sql.SqlComponent
在内部使用org.springframework.jdbc.core.JdbcTemplate
类,并且此 JDBC 模板也与org.springframework.transaction.PlatformTransactionManager
集成。
正如您所见,必须有 这个接口的一些 实现。根据具体情况,您可以配置所需的平台事务管理器。
3.4.3.1. 本地平台TransactionManager 实现
以下列表总结了 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 资源。但是,无法同时列出事务中任何其他种类的资源。此外,比原生 Hibernate API 首选 JPA API。
另外还有其他常用的,平台TransactionManager 的实现
。
3.4.3.2. 全局 PlatformTransactionManager 实现
Spring Framework 提供了一个全局事务管理器实现,供 OSGi 运行时使用。org.springframework.transaction.jta.JtaTransactionManager
支持事务中的多个资源的操作。此事务管理器支持 XA 事务 API,并可在事务中列出多个资源。要使用此事务管理器,您必须将应用程序部署到 OSGi 容器或 iwl 服务器。
虽然 PlatformTransactionManager
的单资源实现是实际 实现,但JtaTransactionManager
更是标准 javax.transaction.TransactionManager
的实际实现的打包程序。
这就是为什么最好在一个环境中使用平台事务管理器的 Jta
实现(通过 JNDI 或 CDI)一个已经配置的 TransactionManager
javax.transaction.TransactionManager
实例,通常是 javax.transaction.UserTransaction
。通常,这两个 JTA 接口都通过单个对象/服务来实施。
以下是配置/使用 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 服务注册表获取。