2013-06-18 35 views
4

目前,我有一种JPA实体用于某种任务。有些进程会写入该表,并且计划的进程将对该任务起作用,并在准备就绪时更改状态。我需要确定任务的优先顺序,并在失败时以降低的频率重试它们。我的环境是通过Hibernate + MySQL + XA事务的GlassFish 3 + JPA。在中期内,该项目将通过Spring解决方案(使用Jetty等)取代GlassFish。如何使用JPA编写生产者 - 消费者

它以某种方式得到了这个工作,但我对它并不满意:我得到了OptimisticLockExceptions,看起来我没有在某些点上获得正确的事务,而且GlassFish上的JPA计时器也有点混乱你需要可变的时间。

我有这种感觉,我在这里使用了错误的工具,而且我应该使用一些成熟稳定的设计,而不是一起杵在一起。使用JPA实体似乎是沉重的,但原始JDBC看起来更糟糕的选择。当然,我想避免沉重的图书馆依赖性,但也许我忽略了针对特定问题的简单“罐装”解决方案(这看起来并不常见)。

[编辑]

为了澄清:我不会改变用途的情况下(我甚至不具备的代码了),我只是想获得一些一般原则,以“做正确“(TM)下一次。为了回答ben75提出的问题:工作人员可能是多线程的,而且我需要小型交易,因为它应该一直运行 - 也许几个月。

+0

你的工作进程是单线程吗?谁确定优先级(工人或生产者或...)?你什么时候获得OptimisticLocking(在任务执行结束时或...)?在整个任务执行期间你有单一交易吗? – ben75

回答

1

我认为你只需要尝试从上面看到事物以便识别过程中的角色&检测任务的创建者,任务的处理器和优先级控制器之间的依赖关系。之后,为每个角色设计干净的可重用EJBs/Services。

有时,对于只需要10-20秒的相对较短的任务,强制用户使用异步EJB(搜索@Asynchronous)而不是创建任务更有意义。

关于OptimisticLockExpcetions:这些可能发生是因为数据同时发生更改,这可能是由任务使用者的其他线程中的一个或由更改数据的客户端引起的。找出原因,如果这是第一种情况,请纠正错误。当然,如果你提供一些代码或解释如何运作,你会得到更多的帮助。

处理任务时:我会用悲观锁取回任务实体,以便另一个线程不会开始处理相同的任务。

所以我想你的过程很复杂,你需要一个更好/更灵活的设计。

+0

这些已经是一些很好的想法,例如我从来没有尝试过'@ Asynchronous'。 – Landei