只是一点点背景,我是一名新开发人员,在高级开发人员离开公司之后,他最近接管了一个重大项目,然后才能全面了解他如何构建这个项目。我会尽力解释我的问题。
此应用程序创建多个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。()在内的所有内容。
答案 0 :(得分:4)
当底层数据库锁定未提交的更改时,会出现此类问题。
我怀疑是某些其他代码在事务外或事务中的userData表上进行了插入/删除,这需要很长时间才能执行,因为它是批处理作业或类似工作。您应该分析引用这些表的所有代码,并查找缺少的@Transactional。
答案 1 :(得分:3)
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,那么它是正常的&#34;得到REQUIRES_NEW的问题...... (有些人可能更喜欢例外&#34;不支持嵌套交易&#34;)
答案 2 :(得分:1)
除this answer旁边,您还可以检查交易的隔离级别 - 可能是限制性太强。
update()
方法是否会永久挂起,还是在超时时抛出异常?
答案 3 :(得分:1)
不幸的是,Propagation.REQUIRES_NEW
遇到了同样的问题。删除它可以解决问题。调试器向我显示提交方法挂起(从@Transactional
方面实现调用)。
问题仅出现在测试弹簧上下文中,当应用程序部署到应用程序服务器时,它可以正常工作。