如何使用JPA会话实现Concurrent GetOrCreate?

时间:2012-01-18 20:36:07

标签: java spring session jpa transactions

我需要在spring-jpa(hibernate)驱动的Web应用程序中实现一个实体的GetOrCreate(我称之为ensureExists)。
我有一个分层应用程序(WS / Services / DAL / Datastore),我想在服务层(弹簧驱动)中实现这个功能。
基本思路是:

  1. 找到实体
  2. 如果找到则返回。
  3. 否则坚持实体。
  4. 如果一切正常,请将其退回。
  5. 如果发生了唯一约束违规,请尝试再次查找该实体并将其返回。
  6. 问题产生于这样一个事实:一旦抛出异常,就应该关闭并重新打开hibernate会话(来自Session的documentation),这使得第5步无效,但我仍然希望将此逻辑封装在服务层中(并没有它驻留在DAL或WS中)。

    我很想听听有关如何解决这个问题的建议,我有一个想法,但我希望在发布之前听到一些意见,而不是倾斜答案。

    提前致谢

    更新
    我想到的解决方案如下:
    将第3阶段重构为包范围服务,该服务具有单个ensureExists方法(使用泛型),该方法接受该类型的Dao和实体并且具有REQUIRES_NEW的传播。此方法将尝试持久化,如果失败,当然会抛出将在原始服务中捕获的异常,并且如果抛出该异常,它将尝试持久化。
    我希望得到一些关于如何实现这一点的反馈意见 如果没有人会在几天内提出建议,我会将其作为代码样本的答案发布并接受。

1 个答案:

答案 0 :(得分:0)

要查找实体,您可以使用条件api + reflection来填充所有重要属性并按样本对象搜索。 要解决concurency问题,请考虑悲观锁定。 当您加载时,只需将锁​​定放在该对象上,并在完成所有事务后释放此锁定。 不确定它是否是关于性能的最佳选择,但你不应该在这里得到例外。