9.4. 事务传播策略
如果要影响事务客户端创建新事务的方式,您可以使用 JmsTransactionManager
并为其指定事务策略。特别是 Spring transaction 策略,您可以指定事务的传播行为。例如,如果事务客户端要创建新事务,并且它检测到该事务已与当前线程关联,是否应该会失败并创建新的事务,并挂起旧的事务?或者说是否让现有事务接管?通过在事务策略中指定传播行为来监管这些行为。
事务策略在 Blueprint XML 中实例化。然后,您可以通过提供 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 行为的事务策略的 bean PROPAGATION_REQUIRES_NEW
ID
。请参阅 第 9.4.3 节 “在 Blueprint XML 中定义策略 Bean”。
9.4.1. 关于 Spring 事务策略
Apache Camel 可让您使用 org.apache.camel.spring.spi.spring.spi.SpringTransactionPolicy
类来定义 Spring 事务策略,它基本上是一个围绕原生 Spring 类的打包程序。SpringTransactionPolicy
类封装了两部分数据:
-
对
PlatformTransactionManager
类型的事务管理器的引用 - 传播行为
例如,您可以使用 PROPAGATION_MANDATORY
行为实例化 Spring transaction 策略,如下所示:
<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. 传播行为的描述
Spring 支持以下传播行为。这些值最初基于 JavaeEE 支持的传播行为:
- PROPAGATION_MANDATORY
- 支持当前的事务。如果不存在当前事务,则抛出异常。
- PROPAGATION_NESTED
如果当前事务存在,则在嵌套的事务中执行,其他行为与
PROPAGATION_REQUIRED
类似。注意所有事务管理器不支持嵌套事务。
- PROPAGATION_NEVER
- 不支持当前的事务。如果当前事务存在,则抛出异常。
- PROPAGATION_NOT_SUPPORTED
不支持当前的事务。始终以非处理方式执行。
注意此策略要求当前事务被暂停,这是所有事务管理器不支持的功能。
- PROPAGATION_REQUIRED
- (默认)支持当前事务。如果不存在,创建一个新名称。
- PROPAGATION_REQUIRES_NEW
创建一个新事务,挂起当前事务(如果存在)。
注意所有事务管理器都不支持挂起事务。
- PROPAGATION_SUPPORTS
- 支持当前的事务。如果不存在,则以非事务方式执行。
9.4.3. 在 Blueprint 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");
使用这种方法时,PR OPAGATION_NEVER
策略不可避免地中止每个事务,从而导致事务回滚。您应该能轻松查看这对应用程序的影响。
请记住,传递到 transacted()
的字符串值是一个 bean ID
,而不是传播行为名称。在本例中,将选择 bean ID
与传播行为名称相同,但这不是必须的。例如,如果您的应用程序使用多个事务管理器,您可能会遇到多个具有特定传播行为的策略。在这种情况下,您不能在传播行为后直接命名 Bean。
9.4.5. 蓝图 XML 中的 PROPAGATION_N
EVER 策略示例
以上路由可以在 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>