9.4. 事务传播策略
如果要影响事务客户端创建新事务的方式,您可以使用 JmsTransactionManager
并为它指定一个事务策略。特别是,Spring 事务策略允许您为事务指定传播行为。例如,如果事务客户端是创建新的事务,它检测到已与当前线程关联的事务,如果它继续并创建新的事务,请暂停旧的事务?或者应该让现有交易接管?通过指定事务策略上的传播行为,可以控制这些类型的行为。
事务策略在蓝图 XML 中作为 Bean 进行实例化。然后,您可以通过将其 bean ID
作为 transacted ()
DSL 命令的参数来引用事务策略。例如,如果要启动受行为的事务( PROPAGATION_REQUIRES_NEW
),您可以使用以下路由:
from("file:src/data?noop=true") .transacted("PROPAGATION_REQUIRES_NEW") .bean("accountService","credit") .bean("accountService","debit") .to("file:target/messages");
其中 PROPAGATION_REQUIRES_NEW
参数指定使用 PROPAGATION_REQUIRES_NEW
行为配置的事务策略 bean 的 bean ID
。请参阅 第 9.4.3 节 “在蓝图 XML 中定义策略 Bean”。
9.4.1. 关于 Spring 事务策略
Apache Camel 可让您使用 org.apache.camel.spring.spi.SpringTransactionPolicy
类来定义 Spring 事务策略,这基本上是一个围绕原生 Spring 类的打包程序。SpringTransactionPolicy
类封装了两部分数据:
-
对
PlatformTransactionManager
类型的事务管理器的引用 - 传播行为
例如,您可以使用 PROPAGATION_MANDATORY
行为实例化 Spring 事务策略 bean,如下所示:
<blueprint ...> <bean id="PROPAGATION_MANDATORY "class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager" /> <property name="propagationBehaviorName" value="PROPAGATION_MANDATORY" /> </bean> ... </blueprint>
9.4.2. propagation 行为的描述
Spring 支持以下传播行为。这些值最初在 JavaeEE 支持的传播行为上建模:
- PROPAGATION_MANDATORY
- 支持当前的事务。如果没有当前事务,则抛出异常。
- PROPAGATION_NESTED
如果存在当前的事务,请在嵌套的事务中执行,否则行为类似于
PROPAGATION_REQUIRED
。注意所有事务管理器都不支持嵌套事务。
- PROPAGATION_NEVER
- 不支持当前的事务。如果当前事务存在,则抛出异常。
- PROPAGATION_NOT_SUPPORTED
不支持当前的事务。始终以非事务方式执行。
注意此策略需要暂停当前的事务,此功能不受所有事务管理器的支持。
- PROPAGATION_REQUIRED
- (默认)支持当前事务。如果不存在,则创建一个新名称。
- PROPAGATION_REQUIRES_NEW
创建新的事务,并暂停当前事务(如果存在)。
注意所有事务管理器都不支持挂起事务。
- PROPAGATION_SUPPORTS
- 支持当前的事务。如果不存在,则以非事务方式执行。
9.4.3. 在蓝图 XML 中定义策略 Bean
以下示例演示了如何为所有支持的传播行为定义事务策略 Bean。为方便起见,每个 bean ID 与传播行为值的指定的值匹配,但实践中,您可以使用您要用于 bean ID 的任何值。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <bean id="PROPAGATION_MANDATORY " class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager" /> <property name="propagationBehaviorName" value="PROPAGATION_MANDATORY" /> </bean> <bean id="PROPAGATION_NESTED" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager" /> <property name="propagationBehaviorName" value="PROPAGATION_NESTED" /> </bean> <bean id="PROPAGATION_NEVER" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager" /> <property name="propagationBehaviorName" value="PROPAGATION_NEVER" /> </bean> <bean id="PROPAGATION_NOT_SUPPORTED" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager" /> <property name="propagationBehaviorName" value="PROPAGATION_NOT_SUPPORTED" /> </bean> <!-- This is the default behavior. --> <bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager" /> </bean> <bean id="PROPAGATION_REQUIRES_NEW" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager" /> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW" /> </bean> <bean id="PROPAGATION_SUPPORTS" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager" /> <property name="propagationBehaviorName" value="PROPAGATION_SUPPORTS" /> </bean> </blueprint>
如果要将任何这些 bean 定义粘贴到您自己的蓝图 XML 配置中,请记得自定义对事务管理器的引用。也就是说,将对 txManager
的引用替换为您的事务管理器 bean 的实际 ID
。
9.4.4. Java DSL 中带有 PROPAGATION_NEVER
策略的示例路由
演示该事务策略对事务有一些影响的简单方式是将 PROPAGATION_NEVER
策略插入到现有事务的中间,如以下路由所示:
from("file:src/data?noop=true") .transacted() .bean("accountService","credit") .transacted("PROPAGATION_NEVER") .bean("accountService","debit");
以这种方式使用,PROPAGATION_NEVER
策略可避免中止每个事务,从而导致回滚。您应该能轻松查看对应用的影响。
请记住,传递给 transacted ()
的字符串值是一个 bean ID
,而不是传播行为名称。在本例中,选择 bean ID
与传播行为名称相同,但这并非总是如此。例如,如果您的应用程序使用多个事务管理器,则最终可能会有多个具有特定传播行为的策略 Bean。在这种情况下,您无法在传播行为后简单地命名 Bean。
9.4.5. 蓝图 XML 中带有 PROPAGATION_NEVER
策略的路由示例
前面的路由可以在 Blueprint XML 中定义,如下所示:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <route> <from uri="file:src/data?noop=true" /> <transacted /> <bean ref="accountService" method="credit" /> <transacted ref="PROPAGATION_NEVER" /> <bean ref="accountService" method="debit" /> </route> </camelContext> </blueprint>