1

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

  1. 消息在 T1(事务 1)中创建并放入出站队列。T1 终止。
  2. 消息由不同的线程从队列中取出,发送和更新发送时间和一些附加信息。设置消息对象的属性并调用 dao.update(m),t2 开始。
  3. 在 t2 提交之前,接收到传递报告并且 Tread3 开始处理相同的消息对象,方法是在 db 中找到它(保存在步骤 1 中),更新它的 state 属性并调用 dao.upate(m) 以便 t3 在 t2 仍在进行中时启动。
  4. 另一个线程(线程 4)通过在 t4 中再次更改它的状态来进一步处理相同的消息对象。

不时发生的结果是,从 t2 开始的更改丢失,db 中的发送时间为空。我需要帮助来弄清楚如何改进应用程序设计并通过防止并发处理同一消息来消除此问题。

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

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

应用程序使用带有休眠实现的 spring 3 和 JPA2。

4

1 回答 1

0

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

另外,如果可能的话,尽量简化一些事情,这样你就只访问数据库一次。如果您确实需要四个单独的更新,请在同一线程的同一事务中按顺序运行它们。否则,您将无法愉快地尝试使交易生效。

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

编辑:回应OP的评论:

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

也许将传递报告放在消息队列中。然后想出一个策略,在 T3 中找到该项目,如果存在则进行更新,如果不存在则稍后再试。

如果您知道在收到交货报告和 T2 事务结束之间有最短或平均时间量,也许您可​​以将该延迟量构建到处理交货收据以创建 T3 更新。

于 2012-10-27T15:22:21.963 回答