5

只是一点背景,我是一名新开发人员,在高级开发人员离开公司后,我最近接手了一个重大项目,我还没有完全了解他是如何构建这个项目的。我会尽力解释我的问题。

此应用程序创建多个 MessageListner 线程以从 JMS 队列中读取对象。一旦接收到对象,数据就会根据某些业务逻辑进行操作,然后映射到持久性对象,以使用休眠的 EntityManager 保存到 oracle 数据库。

直到几周前,自从我加入该项目以来,在过去一年左右的时间里,这种配置还没有出现任何重大问题。但是对于其中一个队列(问题与此特定队列隔离),处理接收到的对象的 spring 托管 bean 在下面的方法中挂起。我的调试使我得出结论,它已完成方法中的所有内容,但在完成时挂起。经过数周的尝试解决此问题后,我对这个问题束手无策。对此的任何帮助将不胜感激。

由于每个 MessageListner 都有自己的处理器,因此这种挂起方法只影响一个队列上的传入数据。

@Transactional(propagation = Propagation.REQUIRES_NEW , timeout = 180)
 public void update(UserRelatedData userData, User user,Company company,...)
 { 
   ...
   ....
   //business logic performed on user object
   ....
   ......
   entityMgr.persist(user);

   //business logic performed on userData object
   ...
   ....
   entityMgr.persist(userData);

   ...
   ....

   entityMgr.flush();

}

我插入调试语句只是为了遍历该方法,它完成了包括 entityMgr.flush.() 在内的所有内容。

4

4 回答 4

9

REQUIRES_NEW 可能会在测试上下文中挂起,因为单元测试中使用的事务管理器不支持嵌套事务......来自 JpaTransactionManager 的 Javadoc:

* <p>This transaction manager supports nested transactions via JDBC 3.0 Savepoints.
 * The {@link #setNestedTransactionAllowed "nestedTransactionAllowed"} flag defaults
 * to {@code false} though, since nested transactions will just apply to the JDBC
 * Connection, not to the JPA EntityManager and its cached entity objects and related
 * context. You can manually set the flag to {@code true} if you want to use nested
 * transactions for JDBC access code which participates in JPA transactions (provided
 * that your JDBC driver supports Savepoints). <i>Note that JPA itself does not support
 * nested transactions! Hence, do not expect JPA access code to semantically
 * participate in a nested transaction.</i>

很明显,如果您不调用 (@Java config) 或在 XML 配置中设置等效标志:

txManager.setNestedTransactionAllowed(true);

或者如果您的驱动程序不支持 Savepoints,则 REQUIRES_NEW 出现问题是“正常的”......(有些人可能更喜欢“不支持嵌套事务”的异常)

于 2017-08-05T07:50:14.060 回答
4

当底层数据库因未提交的更改而锁定时,就会出现此类问题。

我怀疑的是其他一些代码在事务之外的 userData 表上或在需要很长时间才能执行的事务中插入/删除,因为它是批处理作业或类似的。您应该分析引用这些表的所有代码并查找缺少的@Transactional。

于 2011-11-17T09:46:06.757 回答
1

除了这个答案,您还可以检查事务的隔离级别——也许它太严格了。

update()方法是永远挂起,还是在超时过去时抛出异常?

于 2011-11-17T17:55:52.780 回答
1

不幸的是我有同样的问题Propagation.REQUIRES_NEW。删除它可以解决问题。调试器显示提交方法挂起(从@Transactional方面实现调用)。

该问题仅出现在测试 spring 上下文中,当应用程序部署到应用程序服务器时,它工作正常。

于 2012-11-08T08:41:12.813 回答