【发布时间】:2012-01-20 14:22:26
【问题描述】:
我需要在 spring-jpa(休眠)驱动的 Web 应用程序中实现实体的 GetOrCreate(我称之为 ensureExists)。
我有一个分层应用程序(WS/Services/DAL/Datastore),我想在服务层(弹簧驱动)中实现此功能。
基本思路是:
- 查找实体
- 如果发现返回。
- 否则持久化实体。
- 如果一切正常,请退回。
- 如果发生唯一约束违规,请尝试再次查找实体并返回它。
问题源于这样一个事实,即一旦抛出异常,休眠会话应该关闭并重新打开(来自 Session 的documentation),这使得第 5 步无效,但我仍然想将此逻辑封装在服务层中(并且不要让它驻留在 DAL 或 WS 中)。
我很想听听有关如何解决这个问题的建议,我有一个想法,但我想在发布之前听到一些意见,以免答案倾向于它。
提前致谢
更新
我想到的解决方案如下:
将第 3 阶段重构为包范围服务,该服务具有单个 ensureExists 方法(带有泛型),该方法接受该类型的 Dao 和实体并具有REQUIRES_NEW 的传播。此方法将尝试持续存在,如果失败当然会抛出异常,该异常将在原始服务中捕获,如果已抛出异常,它将尝试持续存在。
我希望得到一些关于如何以其他方式实施的反馈。
如果几天后没有人提出其他建议,我会将此作为答案与代码示例一起发布并接受。
【问题讨论】:
-
我会按照你的计划去做,只是我会将步骤 1 到 4 放在一个带有 REQUIRES_NEW 的服务中。
-
@JB Nizet 为什么您认为第 1、2、4 步需要在事务中?此外,在我看来,逻辑上只有第 3 步处于不同的抽象级别,因此有一些理由将其置于不同的服务中。所有其他步骤都具有相同的抽象级别(我认为)。
-
我只是发现有一个“getOrCreate”方法更清楚,它可以抛出异常,如果我愿意,我可以从外部重试。它还将重试逻辑(可以完全通用,提取到代理或拦截器)与特定用例分离。它还允许对创建的实体执行其他操作,而不仅仅是返回它。使用您的系统,您获得的实体会被找到,如果创建则分离。
标签: java spring session jpa transactions