简体   繁体   English

Spring Integration 的 DefaultMessageListenerContainer 和 JPA 中的事务

[英]Transactions in Spring Integration's DefaultMessageListenerContainer and JPA

Let's say I have simple IntegrationFlow which reads JMS messages in asynchronous manner, transforms, applies business logic, etc.假设我有一个简单的IntegrationFlow ,它以异步方式读取 JMS 消息、转换、应用业务逻辑等。

@Bean
public IntegrationFlow upstreamEventFlow() {
    return IntegrationFlows.from(
            Jms.messageDrivenChannelAdapter(jmsConnectionFactory)
                    .configureListenerContainer(container -> container.destinationResolver(destinationResolver))
                    .destination("myQueue")
                    .get()
    )
            .transform(xmlToObjectTransformer)
            .transform(upstreamTransformer)
            .handle(evaluationHandler)
            .transform(objectToXmlTransformer)
            .channel(downstreamEventChannel)
            .get();
}

evaluationHandler is GenericHandler which fetches data from database using JPA and applies some business logic evaluationHandler 是GenericHandler ,它使用 JPA 从数据库中获取数据并应用一些业务逻辑

My question is related to transactions in Spring and Spring Integration我的问题与 Spring 和 Spring Integration 中的事务有关

When I enable logging with following loggers:当我使用以下记录器启用日志记录时:

<logger name="org.springframework.transaction" level="trace"/>
<logger name="org.springframework.jms.connection.JmsTransactionManager" level="debug"/>
<logger name="org.springframework.orm.jpa.JpaTransactionManager" level="debug"/>
<logger name="org.springframework.orm.hibernate5.HibernateTransactionManager" level="debug"/>
<logger name="org.springframework.jdbc.datasource.DataSourceTransactionManager" level="debug"/>
<logger name="org.springframework.integration" level="debug"/>
<logger name="org.springframework.messaging" level="debug"/>
<logger name="org.springframework.jms" level="debug"/>

I can see it all starts with JPA transaction, not transaction created by Spring Integration or at least JMS我可以看到这一切都始于 JPA 事务,而不是由 Spring Integration 或至少 JMS 创建的事务

from logs:从日志:

o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name ...: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager ... for JPA transaction
o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC transaction ...

Why is that?这是为什么?

Could you elaborate on how transactions work in DefaultMessageListenerContainer and how it ties with JMS transactions, JMS transacted sessions, JPA transactions and so on?您能否详细说明事务在DefaultMessageListenerContainer工作方式以及它如何与 JMS 事务、JMS 事务会话、JPA 事务等相关联?

Where is transaction boundary located?交易边界在哪里?

What's the difference between transacted session and using transaction manager in DefaultMessageListenerContainer ?事务会话和在DefaultMessageListenerContainer使用事务管理器有什么区别?

If I throw RuntimeException in handler, I can see it is rolled back and see the message Execution of JMS message listener failed, and no ErrorHandler has been set.如果我在处理程序中抛出RuntimeException ,我可以看到它被回滚并看到消息Execution of JMS message listener failed, and no ErrorHandler has been set. and activemq broker redelivers message multiple times和 activemq 代理多次重新传递消息

Should I set ErrorHandler ?我应该设置ErrorHandler吗?

Best guess is one of your beans, eg evaluationHandler , or the method, is annotated @Transactional .最好的猜测是你的 bean 之一,例如evaluationHandler或方法,被注释为@Transactional That is when the JPA transaction starts.那就是 JPA 事务开始的时候。 The transaction will commit (or rollback) when that method exits.当该方法退出时,事务将提交(或回滚)。

Since the MD channel adapter is transacted by default, the JMS (local) transaction wraps the entire flow and it will not commit (or rollback) until the entire flow completes (or aborts).由于默认情况下对 MD 通道适配器进行事务处理,因此 JMS(本地)事务包装了整个流程,并且在整个流程完成(或中止)之前不会提交(或回滚)。

So, these two transactions are not really synchronized in any way;所以,这两个事务在任何方面都不是真正同步的; they are independent.他们是独立的。

If you inject the JPA transaction manager into the adapter's listener container, the framework will provide "Best Efforts 1PC" transaction synchronization - see Dave Syer's Javaworld Article "Distributed transactions in Spring, with and without XA" .如果将 JPA 事务管理器注入到适配器的侦听器容器中,该框架将提供“Best Efforts 1PC”事务同步——请参阅Dave Syer 的 Javaworld 文章“Spring 中的分布式事务,使用和不使用 XA”

The JPA transaction will be started by the container and both transactions will be committed back-to-back (DB first), effectively synchronizing them. JPA 事务将由容器启动,并且两个事务将背对背(DB 优先)提交,从而有效地同步它们。 This is not true JTA though and there is a small possibility that the DB Tx might commit while the JMS Tx rolls back - so you have to deal with the possibility of duplicate deliveries.然而,这不是真正的 JTA,并且 DB Tx 可能会在 JMS Tx 回滚时提交的可能性很小 - 因此您必须处理重复交付的可能性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM