Spring Bean在@Transactional的方法上挂起

时间:2011-11-17 07:23:59

标签: spring jpa transactional propagation

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

此应用程序创建多个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 个答案:

答案 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方面实现调用)。

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