我在父实体和子实体之间进行简单@OneToMany
映射时遇到问题。一切正常,只有当我从集合中删除子记录时才会删除它们。
父母:
@Entity
public class Parent {
@Id
@Column(name = "ID")
private Long id;
@OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parent")
private Set<Child> childs = new HashSet<Child>();
...
}
孩子:
@Entity
public class Child {
@Id
@Column(name = "ID")
private Long id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="PARENTID", nullable = false)
private Parent parent;
...
}
如果我现在从子集Set中删除子节点,则不会从数据库中删除它。我试图取消child.parent
引用,但这也不起作用。
实体用于Web应用程序,删除是作为Ajax请求的一部分发生的。按下保存按钮时,我没有已删除子项的列表,因此我无法隐式删除它们。
答案 0 :(得分:239)
JPA的行为是正确的(意味着根据规范):对象不会因为您从OneToMany集合中删除它们而被删除。有特定于供应商的扩展可以做到这一点,但原生JPA不能满足它。
部分原因是因为JPA实际上并不知道是否应删除从集合中删除的内容。在对象建模术语中,这是组合和“聚合*。
之间的区别在组合中,没有父项,子实体不存在。 House和Room之间有一个典型的例子。删除房子和房间也是。
聚合是一种更松散的关联,以课程和学生为代表。删除课程,学生仍然存在(可能在其他课程中)。
因此,您需要使用特定于供应商的扩展来强制执行此行为(如果可用)或明确删除子项并将其从父项集合中删除。
我知道:
答案 1 :(得分:69)
除了cletus的回答JPA 2.0,自2010年12月以来的最终版本,在orphanRemoval
注释中引入了@OneToMany
属性。
有关详细信息,请参阅此blog entry。
请注意,由于规范相对较新,并非所有JPA 1提供程序都有最终的JPA 2实现。例如,Hibernate 3.5.0-Beta-2 release尚不支持此属性。
答案 2 :(得分:41)
你可以试试这个:
@OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true)
。
答案 3 :(得分:18)
正如所解释的那样,不可能用JPA做我想要的,所以我使用了hibernate.cascade注释,这样,Parent类中的相关代码现在看起来像这样:
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "parent")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
org.hibernate.annotations.CascadeType.DELETE,
org.hibernate.annotations.CascadeType.MERGE,
org.hibernate.annotations.CascadeType.PERSIST,
org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
private Set<Child> childs = new HashSet<Child>();
我不能简单地使用'ALL',因为这也会删除父亲。
答案 4 :(得分:3)
此处,在“删除”的上下文中,级联意味着如果删除父级,则会删除子级。不是协会。如果您使用Hibernate作为JPA提供程序,则可以使用hibernate specific cascade。
执行此操作答案 5 :(得分:2)
@Entity
class Employee {
@OneToOne(orphanRemoval=true)
private Address address;
}
请参阅here。
答案 6 :(得分:1)
你可以试试这个:
$('.check').click( function () {
var score = 0
var all = $('input[id^=" "]');
var checked = $('input:checked');
var good = $('input:checked[id^=" "]');
checked.siblings().css('color', 'red');
all.siblings().css('color', 'green');
good.each ( function(){
score += 1;
})
alert(score);
score = 0;
});
或
@OneToOne(cascade = CascadeType.REFRESH)