OneToMany 上 CascadeTypes (DEATCH/REMOVE/REFRESH) 的实际用法?

Real world usage for CascadeTypes (DEATCH/REMOVE/REFRESH) on OneToMany?

我真的很难找到 真实世界 中 CascadeType.DETACH、CascadeType.MERGE、CascadeType.REFRESH 的用法OneToMany 关系。

举个例子:

User hasMany UserAccess 

每次用户登录网站时,都会创建一个 UserAccess object,其中包含他的 IP 地址和日期时间。

  1. 上面的 03 个 CascadeType 如何影响现实世界程序中的这种关联?我几乎可以看到 CascadeType.PERSIST(用于级联持久化)和 CascadeType.REMOVE(如果用户被删除则删除 child)的用法。 OrphanRemoval 在这种情况下也是可笑的,毫无疑问。

  2. 如果我的例子不够完整,谁能就这个主题制定一个真实世界的例子?

谢谢!

我很难思考你的例子,因为分离和合并往往适用于将在你的影响范围之外访问的实体。因此,我将坚持使用一些无聊的示例,例如文档集合。

进入示例之前的两点:

首先,理解 Hibernate 级联的一个有用的经验法则是这样想:"If I cascade operation X from A to B then when I call operation X on A Hibernate will automatically call operation X on all of the associated B's. (orphan removal is an exception)"

其次,考虑到这一点,除孤儿移除之外的所有级联的优点只是为您省去了遍历子对象和调用子对象上的操作的麻烦。你自己做和让 Hibernate 做之间没有功能上的区别。

现在,举个例子:

假设您的应用程序跟踪一个 DocumentCollection 对象,该对象具有许多 Document 对象,而 Document 对象又具有许多 Paragraph 对象。您希望此应用程序由其他团队构建的桌面界面使用。您的团队拥有后端,另一个团队拥有前端,但不是 Web 应用程序,所有这些都发生在同一进程中。

为简单起见,该界面将抓取一个 DocumentCollection,因此您的 public API 将只是:

public DocumentCollection fetchCollection(String collectionName);
public void updateCollection(DocumentCollection collection);

现在,因为您不知道界面团队在获取您的 DocumentCollection 后将如何处理它,所以您最不想做的就是将一个活动的、持久的实体传回给他们,事务管理一个人会很可怕。要解决此问题,您需要在发送之前分离任何内容。

现在通常您不需要分离任何东西,因为您无论如何都会在返回对象之前关闭会话,所以让事情变得更复杂。让我们假设您的用户正在与一些多页表单小部件进行交互,并且您希望在小部件的持续时间内保持会话打开(这是每次对话的会话,但老实说,如果您考虑这个示例太久,它会变得人为但这是我能想到的最好的事情了)。

所有这些确实证明了为什么您首先要分离某些东西,我怀疑这比您想象的更能成为您问题的核心。因此,鉴于这种人为设计的场景,您的选择是:

  1. 对 DocumentCollection 调用 detach,遍历每个 Document 并对其调用 detach,然后遍历每个 Paragraph 并对其调用 detach。
  2. 在 DocumentCollection->Document 和 Document->Paragraph 关系上进行级联分离,只需在 DocumentCollection 上调用分离,让 Hibernate 为您进行迭代。

当然,一旦用户完成修改文档并传回保存,那么您将不得不对所有内容调用合并,因此级联合并将非常有用。

为了刷新,让我们看一个不同的例子(这个可能更做作,因为我自己没有做过)。假设您决定信任您的界面团队并且您不想分离对象。这允许您跳过分离和合并的调用。现在,假设用户点击了某种 "revert to last save" 按钮。您决定通过 "refreshing" DocumentCollection 和下面的所有内容来实现它。在这里,级联会非常有用,因为它会为您节省大量迭代。