在我的 Web 应用程序中,我经常需要在单个请求的范围内从数据库中读取实体,并稍后在另一个请求中刷新它们。目前我有一个辅助方法
protected <T> T refresh(T t) {
if (!entityManager.contains(t)) {
t = merge(t);
entityManager.refresh(t);
}
return t;
}
他们的每个方法都会先刷新它正在处理的实体。如果实体已被刷新,则不会发生任何事情。
这很好用,直到后来我意识到这个解决方案有一个重大问题:如果实体已在数据库中同时被修改,则调用失败。merge
显然merge
无法“知道” 的内容t
无论如何都会被立即调用refresh
.
这个问题的正确解决方案是什么?到目前为止,我有这些想法,但没有一个感觉完全令人满意:
而不是调用
merge
andrefresh
,获取实体的 ID 并调用t = find(theClassOfT, t.getId());
这将解决问题,我会得到一个全新的实体,但它有一个主要缺点:我需要知道它的类
T
和它的 ID。获取 ID 可以通过为我的所有实体提供一个顶级超级接口来完成,但是获取类是有问题的(因为 JPA 实现可能会子类化实体,我担心调用t.getClass()
可能会返回某些特定于实现的子类T
)。- 长期只保留 ID,并在每次请求期间读取实体的最新信息。从设计的角度来看,这似乎更正确(无论如何,陈旧的实体都携带无效信息),但再次需要
T
手头的类。
更新:我在请求中保留实体的原因仅仅是为了方便。我特别不需要确保在此期间没有修改实体 - 无论如何我都会在下一个请求时刷新它。