【问题标题】:Commit failure JPA transaction when invoked through JMS MessageListener通过 JMS MessageListener 调用时提交失败的 JPA 事务
【发布时间】:2019-08-30 12:51:11
【问题描述】:

我有一个代码可以正常工作,但在负载高时会失败。无法找到它的路径原因。 以下是我的用例概述

  1. 我正在从 JMS 队列中读取消息。
  2. 使用收到的消息调用一个 REST API 端点。
  3. 将从 #2 收到的响应保存在我的数据库中。

下面是代码sn-p

 //Message Listener class which reads the messages from JMS Queue
 public class MyListener implements MessageListener {
        @Autowired
        MyDao myDao;

        @Override
        public void onMessage(Message message) {
             MyResponse resp = callRest(message);
             myDao.saveToDb(resp);
       }
    }

    //DAO class which updates my entity   
    @Component
    public class MyDao {
          @Autowired
          EntityManager entityManager;

          @Transactional
           public boolean saveToDb(MyResponse resp) {
             Query query = entityManager.createQuery("from MyTable mt where mt.id=:id");
             query.setParameter("id", myResp.getId());
             MyTable myTab = (MyTable) query.getSingleResult();
             myTab.setProcessFlag(true);
             entityManager.merge(myTab);
          }
     }

当我在调试模式下运行或消息不那么频繁地进入队列时,这可以正常工作。

但是当队列中的消息非常快时,我会遇到异常 在saveToDb方法中作为

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction

我在这里做错了什么,或者当多个线程同时访问它时 JMS 和 JPA 事务之间存在一些混淆?

提前致谢。

【问题讨论】:

  • 你没有提到你的 JMS 提供者,但是几个 JMS 实现会从多个线程调用 onMessage。所以你可以从多个线程调用 saveToDb 方法。我不确定您的交易实际从哪里开始,但如果您同步您的 saveToDb() 方法 (public boolean synchronized saveToDb(MyResponse resp)) 是否有效?

标签: spring spring-data-jpa jms spring-transactions transactional


【解决方案1】:

当您调用也标记为@Transactional 的嵌套方法/服务时会发生此异常。

For more details

【讨论】:

    猜你喜欢
    • 2016-10-23
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    相关资源
    最近更新 更多