CascadeType的含义是什么?所有的@ManyToOne JPA关联

我想我误解了在@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)?

443823 次浏览

在这里看到的是OpenJPA文档中的一个例子。CascadeType.ALL表示它将执行所有操作。

引用:

CascadeType。PERSIST:当持久化一个实体时,也持久化其字段中持有的实体。我们建议这个级联规则的自由应用,因为如果EntityManager发现一个字段在刷新期间引用了一个新实体,而该字段没有使用CascadeType。PERSIST,这是一个错误。

CascadeType。REMOVE:当删除一个实体时,它也会删除该字段中包含的实体。

CascadeType。REFRESH:刷新一个实体时,也会刷新该字段中的实体。

CascadeType。MERGE:合并实体状态时,也合并该字段中持有的实体。

塞巴斯蒂安。

来自EJB3.0规范:

级联注释元素的使用可以用来传播 操作对关联实体的影响。的级联

如果X是一个受管实体,删除操作将使其成为 移除。删除操作级联到X引用的实体, 如果从X到这些其他实体的关系被注释为

.使用cascade=REMOVE或cascade=ALL注释元素值

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

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

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

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

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

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

orphanRemoval=trueCascadeType.REMOVE之间的更多解释是在这里

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

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

因此,你应该将CascadeType.ALL@ManyToOne关联移动到@OneToMany端,后者也应该使用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。但请记住,当删除用户时,您也将删除连接到用户对象的地址。