我想我误解了在@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
的事实如何影响我的数据(我想是User
)?
CascadeType.ALL
的含义是持久性将所有EntityManager
操作(PERSIST, REMOVE, REFRESH, MERGE, DETACH
)传播(级联)到相关实体。
在你的情况下似乎是一个坏主意,因为删除Address
将导致删除相关的User
。由于用户可以拥有多个地址,因此其他地址将成为孤儿。然而,相反的情况(注释User
)是有意义的 - 如果地址仅属于单个用户,则如果删除此用户,则传播删除属于用户的所有地址是安全的。
顺便说一句:您可能希望在mappedBy="addressOwner"
中添加User
属性,以向持久性提供程序发出连接列应该在ADDRESS表中的信号。
See here以OpenJPA文档为例。 CascadeType.ALL
意味着它将采取一切行动。
引用:
CascadeType.PERSIST:持久化实体时,也会持久保存此字段中的实体。我们建议自由应用此级联规则,因为如果EntityManager在刷新期间找到引用新实体的字段,并且该字段不使用CascadeType.PERSIST,则这是一个错误。
CascadeType.REMOVE:删除实体时,还要删除此字段中保存的实体。
CascadeType.REFRESH:刷新实体时,还刷新此字段中保存的实体。
CascadeType.MERGE:合并实体状态时,还合并此字段中保存的实体。
塞巴斯蒂安
From the EJB3.0 Specification:
可以使用级联注释元素来将操作的效果传播到关联实体。级联功能最常用于父子关系。
如果X是托管实体,则删除操作会导致其被删除。如果从X到这些其他实体的关系使用cascade = REMOVE或cascade = ALL注释元素值进行注释,则删除操作将级联到由X引用的实体。
简而言之,使用CascadeType.All
定义的实体关系将确保所有持久性事件(如父级上发生的持久性,刷新,合并和删除)将传递给子级。定义其他CascadeType
选项为开发人员提供了对实体关联如何处理持久性的更细粒度的控制。
例如,如果我有一个包含页面列表的对象书,我在此列表中添加一个页面对象。如果定义Book和Page之间关联的@OneToMany
注释被标记为CascadeType.All
,则持久化Book将导致Page也被持久化到数据库。
正如我在this article和我的书High-Performance Java Persistence中所解释的那样,你不应该在CascadeType.ALL
上使用@ManyToOne
,因为entity state transitions应该从Parent实体传播到Child实体。
@ManyToOne
方面始终是儿童协会,因为它应该映射底层FK。
因此,将CascadeType.ALL
从@ManyToOne
协会移动到@OneToMany
,mappedBy
应使用the most efficient one-to-many mapping属性,因为它是orphanRemoval=true
。 `
在JPA 2.0中如果要删除地址,如果从User实体中删除它,则可以将CascadeType.REMOVE
(而不是@OneToMany
)添加到orphanRemoval=true
。
CascadeType.REMOVE
和here之间的更多解释是@Entity
public class User {
@OneToMany(mappedBy = "adressOwner", cascade = CascadeType.ALL)
protected Set<Address> userAddresses = new HashSet<>();
}
@Entity
public class Adresses {
@ManyToOne(cascade = CascadeType.REFRESH) @JoinColumn(name = "user_id")
protected User adressOwner;
}
。
如果您只想删除分配给用户的地址而不影响用户实体类,您应该尝试这样的事情:
qazxswpoi
这样您就不必担心在注释中使用fetch了。但请记住,在删除用户时,您还将删除已连接的地址到用户对象。