JPA+Hibernate - 实体关系中的循环 - 级联策略
Posted
技术标签:
【中文标题】JPA+Hibernate - 实体关系中的循环 - 级联策略【英文标题】:JPA+Hibernate - Cycles in entity relationships - Cascade strategy 【发布时间】:2012-11-29 08:59:02 【问题描述】:我有一组相互连接的实体形成一个循环,即父实体 P 与两个子实体 C1 和 C2 具有两个一对多关系,并且每个实体都具有一对多关系与另一个实体A。实体A实现了这些实体(C1,C2)的关联,并定义了关系的属性(它不仅仅是一个连接表)。所有关系都可以双向导航。 这个设计产生了以下问题:假设您总是在根实体 P 上调用实体管理器操作,应该采用什么级联策略才能持久化/合并实体 A? A 应该可以从两条路径级联到达吗?
注意事项: 似乎如果应用程序选择只提供一个级联路径,则可能会出现引发 TransientObjectException 的情况。如果它提供了两条路径,那么这些路径必须完成整个循环,例如可以尝试通过 A 保存 C1。
版本:JPA 2.0、Hibernate core 4.1.7、hibernate-jpa-2.0-api 1.0.1
【问题讨论】:
【参考方案1】:我可以给你我的 2 美分,如果我的回答有点长,请见谅。
如果您有这种级联冲突,可能是因为您的级联方法或域模型没有很好地定义。我会小心地将级联策略推广到整个图或一组不相关的元素。
我的建议是,级联策略应该只应用于紧密联系在一起的数据集,并且是相同类型的,比如 Java 世界中的类及其(私有)内部类。母类与其子类之间的关系也应该是排他的(在 UML 中称为非共享关联)。
当然,您可以不这样做(我们都可能是懒惰的),但最终您可能会在您的单个持久性流(或持久性配置)和您的业务流之间创建一个耦合网络。您将不得不管理大量异常,并围绕您之前放置的级联策略(保存、更新、删除)执行大量配置逻辑。
极端的做法是有些人可能只想保存一个大根对象。为什么不?其余的“应该继续级联”。但事实上,这可能会严重限制系统的可维护性。此外,在加载、保存和合并大图时,您可能需要管理大图在内存中的状态。
如果您使用 Web 应用程序或任何客户端-服务器应用程序,您的 Web 工作流程应该能够在每次请求时保存一组有限的对象,而无需保存根元素中的所有内容。我知道我没有直接回答你的问题。让我们回到你的例子:
假设 P 是一家银行,C1 和 C2 是两个客户,A 是一个产品。
我有两个简单的答案: 1)每一层都可以单独保存,没有任何级联。但它可以在同一个事务中完成,如果你愿意,也可以在同一个 DAO 中完成。
2) P 和 C “可以”级联。但 A 必须保存在不同的工作流程中。
这让我想起了 Peter Coad 的一章,他谈到“领域驱动分析”:http://www.petercoad.com/download/bookpdfs/jmcuch01.pdf
本章解释了如何在不同的原型中分离图中的不同对象。事务数据和描述或“事物”之间的持久性工作流不应该相同。这有助于制定更好的级联策略:
The four archetypes of Peter Coad are:
- Is it a moment or interval?
- Is it a role played?
- Is it a catalog-entry-like description?
- Otherwise, it's a party, place, or thing.
希望对你有帮助。
【讨论】:
【参考方案2】:一般来说,一个好主意是仅在紧密关联中并且仅在父->子(或所有者->拥有)方向上级联。在您的情况下,它可能是P->C1
和P->C2
。由于A
没有一个明显的父级,所以应该单独保存。这可以在你的 DAO 中提到的@etienno 与P
(和C1
,C2
)一起在单个事务中完成。我不知道你的域模型,但也许 A
在概念层面上是一个单独的实体,在这种情况下单独保存更合理。
从长远来看,级联到许多不密切相关的对象可能会使整个图在变大时变得难以管理。
在这种情况下,最好问“如果没有 Hibernate,你会怎么做”这个问题。在您的情况下,您可能首先保存P
,然后是C1
、C2
,然后是A
。 AFAIK JPA/Hibernate 没有提供任何明确的方式来强制执行这种顺序,所以有些事情必须由您手动完成。
【讨论】:
以上是关于JPA+Hibernate - 实体关系中的循环 - 级联策略的主要内容,如果未能解决你的问题,请参考以下文章
hibernate/jpa 忽略 @XxxToOne 关系中的 LAZY FETCHING
hibernate/jpa double OneToOne 与一个实体的双向关系