我很难找出OneToMany关系中CascadeType.DETACH,CascadeType.MERGE,CascadeType.REFRESH的实际用法。

让我们举一个例子:

User hasMany UserAccess


每次用户登录网站时,都会创建一个包含其IP地址和DateTime的UserAccess对象。


上面的03个CascadeTypes在现实过程中如何影响这种关联?我几乎可以看到CascadeType.PERSIST(用于级联持久化)和CascadeType.REMOVE(如果删除了User则删除子级)的用法。毫无疑问,在这种情况下,OrphanRemoval也很可取。
如果我的例子不够完整,那么有人可以在这个问题上提出一个真实的例子吗?


谢谢!

最佳答案

我很难考虑您的示例,因为分离和合并往往是针对那些将在您的影响范围之外访问的实体。因此,我将坚持一些无聊的示例,例如文档集合。

在进入示例之前有两点:

首先,了解Hibernate级联的一个有用的经验法则是这样思考:“如果我将操作X从A级联到B级,那么当我在A上调用操作X时,Hibernate将自动在所有关联的B上调用操作X 。(孤立删除是一个例外)”

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

现在,以示例为例:

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

为简单起见,该接口将抓取DocumentCollection批处理,因此您的公共API只需为:

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


现在,由于您不知道接口团队在获取DocumentCollection之后将如何处理它们,那么您要做的最后一件事就是将一个活动的持久性实体传递回给他们,仅是事务管理就很糟糕。要解决此问题,您需要先分离任何东西,然后再发送。

现在,通常您实际上并不需要分离任何东西,因为无论如何您都将在返回对象之前关闭会话,因此可以使事情进一步复杂化。让我们假设您的用户正在与某个多页表单窗口小部件进行交互,并且您希望在窗口小部件的持续时间内保持会话打开(这是每次会话,但老实说,如果您考虑该示例的时间过长,它将变得虚构,但是这是我能做到的最好的选择。

所有这些都确实说明了为什么您首先要分离某些东西是合理的,我怀疑这比您想像的更重要。因此,考虑到这种人为的情况,您的选择是:


在DocumentCollection上调用detach,遍历每个Document并在其上调用detach,然后在每个Paragraph中进行遍历并在那些上调用detach。
在DocumentCollection-> Document和Document-> Paragraph关系上进行Cascade分离,然后在DocumentCollection上调用detach,让Hibernate为您完成迭代。


当然,一旦用户完成了对文档的修改并将其传递回保存以保存它,那么您将必须对所有内容调用merge,因此级联合并将非常有用。

为了刷新,让我们看一个不同的示例(由于我自己没有做过,所以这个示例可能更人为设计)。假设您确定自己确实信任界面团队,并且不想分离对象。这使您可以跳过要分离和合并的调用。现在,假设用户点击了某种“还原为上一次保存”按钮。您决定通过“刷新” DocumentCollection及其下面的所有内容来实现此目的。在这里,级联将非常有用,因为它可以节省大量迭代。

10-08 18:55