我很难在OneToMany关系中找到CascadeType.DETACH,CascadeType.MERGE,CascadeType.REFRESH的真实世界用法。
让我们举个例子:
User hasMany UserAccess
每次用户登录网站时,都会创建一个包含其IP地址和日期时间的UserAccess对象。
上面的03个CascadeTypes如何在现实世界的程序中影响这种关联?我几乎可以看到CascadeType.PERSIST(用于级联持久化)和CascadeType.REMOVE(用于删除User时删除子项)的用法。 OrphanRemoval在这种情况下也是可以嘲笑的,毫无疑问。
如果我的例子不够完整,有人可以就这个问题制定一个真实世界的例子吗?
谢谢!
答案 0 :(得分:2)
我很难用你的例子思考,因为分离和合并往往是在你的影响范围之外访问的实体。出于这个原因,我会坚持使用像文档集这样无聊的例子。
在我进入示例之前的两点:
首先,理解Hibernate级联的一个有用的经验法则是以这种方式考虑它们:“如果我将操作X从A级联到B级,那么当我在A Hibernate上调用操作X时,将自动调用操作X相关的B。(孤儿删除是一个例外)“
其次,考虑到这一点,除孤儿删除之外的所有级联的优点只是为了省去迭代子对象和调用子对象上的操作的麻烦。你自己做和让Hibernate做它之间没有功能上的区别。
现在,举例:
假设您的应用程序跟踪DocumentCollection对象,该对象具有许多具有许多Paragraph对象的Document对象。您希望此应用程序由其他团队构建的桌面界面使用。你的团队拥有后端,另一个团队拥有前端,但不是一个Web应用程序,所有这一切都发生在同一个过程中。
为了简单起见,界面将获取一个DocumentCollection批发,因此您的公共API将只是:
public DocumentCollection fetchCollection(String collectionName);
public void updateCollection(DocumentCollection collection);
现在,因为你不知道接口团队在获取它之后会对你的DocumentCollection做什么,那么你要做的最后一件事就是将一个实时的,持久的实体传递回给他们,单独的事务管理就是太可怕了要解决此问题,您需要在发送之前分离任何内容。
现在通常你不需要分离任何东西,因为你会在返回对象之前关闭你的会话,所以让事情进一步复杂化。让我们假装你的用户正在与一些多页面窗口小部件进行交互,并且你希望在窗口小部件的持续时间内保持会话打开(这是每次会话的会话,但老实说,如果你长时间考虑这个例子它会变得做作但是这是我能做到的最好的事情。)
所有这一切都证明你为什么要首先分离一些东西是合理的,我怀疑这个问题比你想象的更重要。所以,鉴于这种人为的设想,你的选择是:
当然,一旦用户完成修改文档并将其传回以保存,那么你将不得不在所有内容上调用merge,因此级联合并将非常有用。
对于刷新,让我们看一个不同的例子(这个可能更加做作,因为我自己没有这样做)。假设您确定您信任您的界面团队,并且您不想分离对象。这允许您跳过分离和合并的调用。现在,假设用户点击某种“恢复到上次保存”按钮。您决定通过“刷新”DocumentCollection及其下的所有内容来实现此目的。在这里,级联将非常有用,因为它可以为您节省大量的迭代。