在我的应用程序中,我使用多个弹簧集成通道。我的要求是所有通道中的db操作应该作为单个事务工作。如果所有通道中的db操作都成功,那么只有事务应该提交,否则所有数据库操作都应该回滚。 这是我的代码片段:
MyFirstService.java
@Transactional
public class MyFirstService {
@Resource
private MyFirstRepository myFirstRepository;
@Transactional(propagation = Propagation.REQUIRED)
@ServiceActivator(inputChannel = "my-first-servie-input-channel",
outputChannel = "my-first-servie-output-channel")
public String saveData(final MyEntity myEntity) {
myFirstRepository.save(myEntity);
}
}
MySecondService.java
@Transactional
public class MySecondService {
@Resource
private MySecondRepository mySecondRepository;
@Transactional(propagation = Propagation.REQUIRED)
@ServiceActivator(inputChannel = "my-first-servie-output-channel",
outputChannel = "my-Second-servie-output-channel")
public String saveEntity(final MyTestEntity myTestEntity) {
mySecondRepository.save(myTestEntity);
}
}
弹簧整合-context.xml中
<int:chain input-channel="transaction-inbound-channel" output-channel="my-first-servie-input-channel">
</int:chain>
<int-amqp:inbound-channel-adapter
channel="transaction-inbound-channel"
queue-names="sample.queue"
concurrent-consumers="5"
error-channel="failed-channel"
connection-factory="rabbitConnectionFactory"
mapped-request-headers="*" channel-transacted="true"/>
<rabbit:connection-factory
id="rabbitConnectionFactory"
connection-factory="rcf"
host="${spring.rabbitmq.host}"
port="${spring.rabbitmq.port}"
username="${spring.rabbitmq.username}"
password="${spring.rabbitmq.password}"
/>
<bean id="rcf" class="com.rabbitmq.client.ConnectionFactory">
<property name="host" value="${spring.rabbitmq.host}"/>
<property name="requestedHeartbeat" value="10" />
</bean>
因此,在上面的代码中,如果mySecondRepository.save(myTestEntity);
失败,myFirstRepository.save(myEntity);
应该回滚。
我没有在我的应用程序中的任何地方使用BarrierMessageHandler
。
我在配置类中添加了@EnableTransactionManagement
。
即使我尝试channel-transacted="true"
,仍然没有运气。我在这里错过了什么吗?
我找到了在同一服务的多个方法之间传播单个事务的解决方案 https://softwareengineering.stackexchange.com/questions/163569/how-to-manage-2-dao-methods-in-a-single-transaction 但不是在多个渠道之间。有人可以帮助我实现这一目标。 提前致谢。
答案 0 :(得分:0)
您不关心。无论如何,消息通道操作都是Java方法。所以,同样的TX包装也适用于此。
只关注你应该记住TX是线程限制的,如果你将消息转移到另一个线程,ExecutorChannel
,QueueChannel
,PublishSubscribeChannel
{{1}等等,TX将被提交,因为你离开了保持线程。
因此,如果您的Executor
和my-first-servie-output-channel
为my-first-servie-output-channel
,那么一切正常,您的TX也将包装第二个存储库调用。只是因为一切都在同一个线程中完成。
当然,使用DirectChannel
有一个技巧,它可以暂停一个线程,例如使用事务并等待触发器释放它,因此,提交TX。
修改强>
对于从MessageDriven Consumer到直接下游流的传播事务,您应该在那里提供事务。
BarrierMessageHandler
是特定的,并且是RabbitMQ频道的本地特征。它与您的存储库完全无关。
为此,channel-transacted
支持:
<int-amqp:inbound-channel-adapter>
<xsd:attribute name="transaction-manager" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
The PlatformTransactionManager to use when the Consumer receives the AMQP Message and the Listener is invoked.
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
可以是对您的下游服务足够的任何实现。