首页 文章

JPA Hibernate - 实体关系中的循环 - 级联策略

提问于
浏览
10

我有一组相互连接的实体形成一个循环,即父实体P与两个子实体C1和C2有两个一对多的关系,并且这些实体中的每一个都与另一个实体具有一对多的关系A.实体A实现这些实体(C1,C2)的关联并定义关系的属性(它不仅仅是一个连接表) . 所有关系都可以在两个方向上导航 .

domain objects

这个设计产生了以下问题:如果您总是在根实体P上调用实体管理器操作,那么级联策略应该是什么,以便实体A可以被持久化/合并? A是否可以从两条路径到达级联?

Considerations: 似乎如果应用程序选择只提供一个级联路径,则可能会出现抛出TransientObjectException的情况 . 如果它提供两个路径,则这些路径必须进行完整循环,例如可以尝试通过A保存C1 .

版本:JPA 2.0,Hibernate核心4.1.7,hibernate-jpa-2.0-api 1.0.1

2 回答

  • 3

    我可以给你2美分,对不起,如果我的回答有点长 .

    如果您有这种级联冲突,可能是因为您的级联方法或域模型没有很好地定义 . 我会小心地将级联策略概括为整体图或一组不相关的元素 .

    我的建议是,级联策略只应用于强绑定在一起的数据集,并且应该用于相同类型的数据集,例如java世界中的类及其(私有)内部类 . 母班与其子女之间的关系也应该是排他性的(在UML中称为非共享关联) .

    当然,你可以做其他事情(我们都可以懒惰),但最后你可以在你的单一持久性流程(或持久性配置)和业务流程之间创建一个耦合网络 . 您将不得不管理许多异常,并围绕您之前放置的级联策略(保存,更新,删除)执行大量配置逻辑 .

    极端的方法是有些人可能只想保存一个大的根对象 . 为什么不?其余的“应该坚持级联” . 但实际上,这可能会严重限制系统的可维护性 . 此外,您可能必须在加载,保存和合并时管理内存中大图的状态 .

    如果您执行Web应用程序或任何客户端 - 服务器应用程序,您的Web工作流应该能够在每个请求中保存一组有限的对象,而无需保存根元素中的所有内容 . 我知道我没有直接回复你的问题 . 让我们回到你的例子:

    假设P是Bank,C1和C2是两个客户端,A是产品 .

    我有两个简单的答案:1)每个层可以单独保存,无需任何级联 . 但它可以在同一个事务中完成,如果你愿意,可以在同一个DAO中完成 .

    2)P和C“可以”级联 . 但是A必须保存在不同的工作流程中 .

    这让我想起彼得·科德的一章,他在那里谈到了一个"Domain Driven Analysis":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.
    

    我希望它有所帮助 .

  • 3

    通常,一个好主意是仅在密切关联中并且仅在 parent->child (或所有者 - >拥有)方向上级联 . 在你的情况下,它可能是 P->C1P->C2 . 由于 A 没有一个明显的父级,因此应单独保存 . 这可以通过@etienno在单个事务中与 P (和 C1C2 )一起在DAO中提到来完成 . 我不知道你的域模型,但是甚至 A 在概念层面上也是一个单独的实体,在这种情况下,单独的保存甚至更合理 .

    级联到许多不紧密相关的对象可能会在长期内使整个图形变大,变得无法管理 .

    在这样的情况下,提问"how would you do it without Hibernate"总是好的 . 在你的情况下,你可能首先保存 P ,然后是 C1C2 ,然后是 A . AFAIK JPA / Hibernate没有提供任何明确的方法来强制执行此类订单,因此有些事情必须由您手动完成 .

相关问题