JPA @ManyToOne与CascadeType.ALL
我想我很想理解在@ManyToOne关系的背景下级联的含义。
案子:
public class User { @OneToMany(fetch = FetchType.EAGER) protected Set<Address> userAddresses; } public class Address { @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) protected User addressOwner; }
cascade = CascadeType.ALL的含义是什么? 例如,如果我从数据库中删除某个地址,我添加cascade = CascadeType.ALL的事实如何影响我的数据(用户我猜)?
CascadeType.ALL
的含义是持久性将传播(级联)所有EntityManager
操作( PERSIST, REMOVE, REFRESH, MERGE, DETACH
)到相关的实体。
在你的情况下,似乎是一个坏主意,因为删除Address
将导致删除相关的User
。 作为一个用户可以有多个地址,其他地址将成为孤儿。 然而,反例(注释User
)是有意义的 – 如果一个地址只属于一个用户,如果这个用户被删除,传播删除所有属于用户的地址是安全的。
顺便说一句:你可能想要为你的User
添加一个mappedBy="addressOwner"
属性来通知持久化提供者连接列应该在ADDRESS表中。
请参阅 OpenJPA文档中的示例。 CascadeType.ALL
意味着它将执行所有操作。
引用:
CascadeType.PERSIST:当坚持一个实体时,也坚持这个字段中的实体。 我们build议这个级联规则的自由应用,因为如果EntityManager在刷新期间发现一个引用新实体的字段,并且该字段不使用CascadeType.PERSIST,则是错误的。
CascadeType.REMOVE:删除一个实体时,也删除这个字段中的实体。
CascadeType.REFRESH:刷新实体时,也刷新该字段中的实体。
CascadeType.MERGE:合并实体状态时,也合并在该字段中保存的实体。
塞巴斯蒂安
从EJB3.0规范 :
可以使用级联注释元素来将操作的效果传播到关联的实体。 父级 – 子级关系中最常使用级联function。
如果X是托pipe实体,则删除操作会使其被删除。 如果从X到这些其他实体的关系用cascade = REMOVE或cascade = ALL注释元素值进行注释,则删除操作将级联到由X引用的实体。
因此,简而言之,使用CascadeType.All
定义的实体关系将确保所有持久性事件(例如持久化,刷新,合并和移除发生在父级上的事件)都将传递给子级。 定义其他CascadeType
选项为开发人员提供了对实体关联如何处理持久性的更细粒度级别的控制。
例如,如果我有一个包含页面列表的对象Book,并在此列表中添加一个页面对象。 如果定义Book和Page之间的关联的@OneToMany
注释被标记为CascadeType.All
,则坚持Book将导致页面也被持久化到数据库。
在JPA 2.0中,如果你想删除一个地址,如果你从一个用户实体中删除它,你可以添加orphanRemoval=true
(而不是CascadeType.REMOVE
)到你的@OneToMany
。
orphanRemoval=true
和CascadeType.REMOVE
之间的更多解释在这里 。
正如我在本文和我的书“ 高性能Java持久性”中所解释的 ,您不应该在@ManyToOne
上使用CascadeType.ALL
,因为实体状态转换应该从父实体传播到子@ManyToOne
。
@ManyToOne
方面始终是Child关联,因为它应该映射底层的FK。
因此,将CascadeType.ALL
从@ManyToOne
关联移动到应使用mappedBy
属性的@OneToMany
,因为它是最有效的一对多映射 。 `
从关系中删除Cascade = CascadeType.ALL