我想我误解了@多对一关系上下文中级联的含义。

案例:

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这一事实如何。所有影响我的数据(我猜是用户)?


请参阅这里的OpenJPA文档示例。CascadeType。ALL意味着它会做所有的动作。

引用:

CascadeType.PERSIST: When persisting an entity, also persist the entities held in its fields. We suggest a liberal application of this cascade rule, because if the EntityManager finds a field that references a new entity during the flush, and the field does not use CascadeType.PERSIST, it is an error. CascadeType.REMOVE: When deleting an entity, it also deletes the entities held in this field. CascadeType.REFRESH: When refreshing an entity, also refresh the entities held in this field. CascadeType.MERGE: When merging entity state, also merge the entities held in this field.

塞巴斯蒂安。


来自EJB3.0规范:

级联注释元素的使用可用于传播 操作对关联实体的影响。的级联 功能最典型地用于亲子关系。 如果X是一个托管实体,则删除操作将使其成为 移除。删除操作级联到X引用的实体, 如果从X到这些其他实体的关系被注释为 cascade=REMOVE或cascade=ALL注释元素值。

简言之,就是用CascadeType定义的实体关系。All将确保发生在父节点上的所有持久化事件,如持久化、刷新、合并和删除,都将传递给子节点。定义其他CascadeType选项为开发人员提供了对实体关联如何处理持久性的更细粒度级别的控制。

例如,如果我有一个对象Book,它包含一个页面列表,我在这个列表中添加一个页面对象。如果定义Book和Page之间关联的@OneToMany注释被标记为CascadeType。总之,持久化Book会导致Page也被持久化到数据库。


CascadeType的含义。ALL是指持久化将传播(级联)所有EntityManager操作(PERSIST, REMOVE, REFRESH, MERGE, DETACH)到相关实体。

在您的情况下,这似乎是一个坏主意,因为删除一个地址将导致删除相关的用户。由于一个用户可以有多个地址,其他地址将成为孤儿。然而,相反的情况(注释User)是有意义的-如果一个地址只属于一个用户,如果该用户被删除,传播属于该用户的所有地址的删除是安全的。

顺便说一句:你可能想要给你的User添加一个mappedBy="addressOwner"属性来向持久化提供程序发出信号,表明连接列应该在ADDRESS表中。


在JPA 2.0中,如果你想从用户实体中删除一个地址,你可以添加orphanRemoval=true(而不是CascadeType.REMOVE)到你的@OneToMany。

orphanRemoval=true和CascadeType之间的更多解释。REMOVE在这里。


你不应该使用CascadeType。@ManyToOne上的ALL,因为实体状态转换应该从父实体传播到子实体,而不是相反。

@ManyToOne在关联的子端,因为它映射了底层的外键列。

因此,您应该移动CascadeType。从@ManyToOne关联到@OneToMany端的ALL,也应该使用mappedBy属性,因为它是最有效的一对多表关系映射。


如果你只是想删除分配给用户的地址,而不影响user实体类,你应该尝试这样做:

@Entity
public class User {
   @OneToMany(mappedBy = "addressOwner", cascade = CascadeType.ALL)
   protected Set<Address> userAddresses = new HashSet<>();
}

@Entity 
public class Addresses {
   @ManyToOne(cascade = CascadeType.REFRESH) @JoinColumn(name = "user_id")
   protected User addressOwner;
}

这样你就不需要担心在注释中使用fetch。但请记住,当删除用户时,您也将删除连接到用户对象的地址。