关于春季交易管理重新设计的建议

时间:2012-10-27 13:18:17

标签: java spring hibernate jpa-2.0

我将尝试描述我想要解决的问题。我意识到我开发的应用程序的弹簧事务管理实现不佳。我正在使用声明方法和DAO接口方法(CRUD)上定义的事务,而不是服务层方法。它是一个Web应用程序,可以执行某种消息处理,并且多个线程同时在同一个消息实例上运行。以下是典型序列中的步骤:

  1. 在T1(事务1)中创建消息并将其放入出站队列。 T1终止。
  2. 通过不同的线程从队列中获取消息,随发送时间和一些其他信息发送和更新。设置消息对象的属性并调用dao.update(m),t2 start。
  3. 在t2提交之前,接收到传递报告,并且Tread3开始处理相同的消息对象,方法是在db(在步骤1中保存)中找到它,更新它的state属性并调用dao.upate(m)以便t3在t2静止时启动进行中。
  4. 另一个线程(线程4)通过在t4中再次更改其状态来进一步处理相同的消息对象。
  5. 不时发生的结果是丢失了来自t2的更改,并且db中的发送时间为空。 我需要帮助找出如何改进应用程序设计并通过阻止同时处理同一消息来消除此问题。

    1. 我是否应该专注于事务重新设计(在服务级别而不是dao上使用它)并使用可序列化隔离级别(或其他)或

    2. 我应该使用JPA实体管理器锁定吗?

    3. App将spring 3和JPA2与hibernate实现结合使用。

1 个答案:

答案 0 :(得分:0)

是的,我将事务移动到服务级别,但我重新考虑整个设计,看看是否可以将整个过程放到一个线程中。如果我没记错的话,Spring的事务管理是基于线程的 - 我怀疑你是否能够拥有跨越线程的事务。

另外,如果可能的话,尽量简化一些事情,这样你只能打一次数据库。 如果您确实需要四个单独的更新,请在同一个线程中的同一事务中按顺序运行它们。否则,您将无法及时尝试让交易发挥作用。

显式锁定也要求一个受伤的世界 - 你很可能会遇到死锁。

编辑:回应OP的评论:

我建议找到一种方法将T3更新与T2更新分开,并在执行T3更新之前让T2事务提交。

或许将传递报告放在消息队列中。 然后提出一种策略,用于在T3中查找项目并进行更新(如果存在),或者稍后再尝试(如果不存在)。

如果您知道在收到交货报告和T2交易结束之间存在最短或平均时间,您可能会在处理交货收据时建立延迟时间以创建T3更新。