【问题标题】:Spring - commit JMS Transaction after JPA transactionSpring - 在 JPA 事务之后提交 JMS 事务
【发布时间】:2016-10-23 10:52:30
【问题描述】:

我有两个事务管理器:JpaTransactionManager (myJpaTm) 和 JmsTransactionManager (myJmsTm)。

考虑以下代码:

@Named
public class TestA {
   @Inject TestB testB;

   @Transactional(transactionManager="myJpaTm") 
   public void methoda() {
     // store stuff in db
     testB.methodb();
   }
}

@Named
public class TestB {

   @Transactional(transactionManager="myJmsTm")  
   public void methodb() {
     // send few JMS messages
   }
}

我们有外部 JPA 事务和内部 JMS 事务,两者是分开的,因为我们没有使用分布式事务。

我想在提交 JPA 事务后立即提交 JMS 事务。在这种情况下,当前 JMS 事务需要连接到父 JPA 事务。

我不是在寻找分布式事务的替代品,我只是想在将数据提交到数据库后发送 JMS 消息。

我知道我可以创建另一个可以调用methoda 然后调用methodb 的类,但我想通过将两个事务连接在一起来解决它。

【问题讨论】:

    标签: java spring jpa jms


    【解决方案1】:

    我过去曾使用 TransactionSynchronizationManager 完成此操作,并在 afterCommit 方法中添加发送消息块以进行同步。基本上你需要在你的实现中放置这样的东西:

    @Named
    public class TestA{
    
    @Inject
    TestB testB;
    
    @Transactional(transactionManager="myJpaTm")
    public void methoda() {
       // other db stuff
       if(TransactionSynchronizationManager.isActualTransactionActive()){
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){
                     @Override
                     public void afterCommit(){
                         testB.methodb();
                     }
             });
        }
      }
    }
    

    【讨论】:

      【解决方案2】:

      我还发现了另一种选择——我们可以使用spring-data-commons 中的ChainedTransactionManager,它将以正确的顺序链接两个事务管理器。

      @Configuration
      public class ChainedTransactionConfiguration {
         @Bean
          public ChainedTransactionManager chainedTransactionManager(
              @Named("myJpaTm") JpaTransactionManager myJpaTm,
              @Named("myJmsTm") JmsTransactionManager myJmsTm) {
          return new ChainedTransactionManager(myJmsTm, myJpaTm);
          }
      }
      

      现在我只需要设置新的 TM:

      @Named
      public class TestA {
         @Inject TestB testB;
      
         @Transactional(transactionManager="chainedTransactionManager") 
         public void methoda() {
           // store stuff in db
           testB.methodb();
         }
      }
      
      @Named
      public class TestB {
      
         @Transactional(transactionManager="myJmsTm")  
         public void methodb() {
           // send few JMS messages
         }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-12-17
        • 2020-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-25
        • 2011-04-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多