我需要在spring-jpa(hibernate)驱动的web应用程序中实现一个实体的GetOrCreate(我称之为ensureExists)。
我有一个分层的应用程序(WS/Services/DAL/Datastore),我想在服务层(spring驱动)中实现这个功能。
的基本思路是:如何使用JPA会话实现并发GetOrCreate?
- 查找实体
- 如果找到返回。
- 否则坚持实体。
- 如果一切正常返回它。
- 如果发生了唯一约束违规,请尝试再次查找实体并将其返回。
问题的事实,一旦有异常抛出Hibernate的Session应该关闭并重新打开(从Session的documentation),这使得第5步无效,但我还是想封装在服务层这一逻辑(出现并没有它驻留在DAL或WS中)。
我很乐意听到关于如何解决这个问题的建议,我有一个想法,但我希望在发布之前听到一些意见,以避免向答案倾斜。
预先感谢
更新
溶液我想到如下:
重构阶段3到封装作用域服务具有单一ensureExists方法(使用泛型),它接受所述道这种类型和实体,并具有REQUIRES_NEW
的传播。这个方法会尝试持久化,如果失败,当然会抛出一个将被原始服务捕获的异常,并且如果该异常被抛出,它将尝试持久化。
我很想谈谈如何以其他方式实现这一点。
如果没有人会在几天内另外提出建议,我会以代码示例的形式发布此答案并接受它。
我会按照你的计划去做,除非我将步骤1到步骤4放在REQUIRES_NEW的服务中。 – 2012-01-20 07:12:58
@JB Nizet为什么你认为步骤1,2,4需要进行交易?另外,在我看来,逻辑上只有第3步处于不同的抽象层次,所以有理由让它坐在不同的服务中。所有其他步骤都具有相同的抽象级别(我认为)。 – Ittai 2012-01-20 13:07:34
我刚刚发现它有一个“getOrCreate”方法,它可以抛出异常,并且如果我想从外部重试,可以更清晰。它也将特定用例的重试逻辑(可以完全通用,提取给代理或拦截器)分离出来。而且它还允许使用创建的实体执行其他操作,而不仅仅是返回它。在你的系统中,你得到的实体被连接,如果被创建,则被分离。 – 2012-01-20 13:12:52