我在我的父实体中设置如下:
Class Parent {
@OneToMany(mappedBy = parent, cascade = CasacadeType.ALL)
Set<Child> children;
}
Class Child {
@Column(nullable=false)
@ManyToOne
Parent parent;
}
现在事件,如果我对其中一个元素的Set执行了remove()操作,它实际上并没有被删除。
答案 0 :(得分:7)
您的映射应如下所示:
public class Parent {
@OneToMany(mappedBy = parent, cascade = CasacadeType.ALL, orphanRemoval = true)
private Set<Child> children = new HashSet<>();
public void removeChild(Child child) {
children.remove(child);
child.setParent(null);
}
}
public class Child {
@ManyToOne
private Parent parent;
}
正如this article中所述,因为您有双向关联,所以必须让双方同步。
因此,最好打电话:
parent.removeChild(child);
这样,removeChild
将从Child
children
中移除Set
,并将Child
parent
关联设置为{ {1}}。
答案 1 :(得分:2)
我有同样的问题,虽然使用remove和setParent为null,但相关数据仍然是db。调试后,我看到相关的子对象无法从父母的子列表中删除。当我搜索&#34; hibernate set删除不工作&#34;在网上,我发现了hibernate真相:remove方法有一些bug,因为hashcode和equals方法。在seing之后我认为removeAll()方法可能正常工作。我把相关的一个对象放到列表中并将列表放到removeAll方法中并且它成功了。举个例子:
List childList = new ArrayList();
childList.add(child);
parent.removeAll(childList);
child.setParent(null);
答案 2 :(得分:0)
实际上,对于使用自定义equals()
和hashCode()
的以下情况,根本原因可能也位于其他地方:
public class Child {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Child(int id) {
this.id = id;
}
//other fields
@Override
public int hashCode() {
return id;
}
@Override
public boolean equals(Object obj) {
//instanceof checks for null, but whatever...
if (obj == null || !(obj instanceof Child)) {
return false;
}
return this.id == ((Child)obj).id;
}
}
在这种情况下,HashTable无法删除对象,因为它“在别处看起来”。当然,这不是错误,而只是HashTable的基本原理之一。
public static void main(String[] args) {
Child child1 = new Child(123);
HashSet<Child> hashSet = new HashSet<>();
hashSet.add(child1); //puts to hash table at position X
child1.setId(321);
hashSet.remove(child1);//looks at position Y
//child1 is still in the set
}
PS:声称这不能回答原始问题在某种程度上是正确的-这不是答案,而是一种解释,并且原始类没有覆盖hashCode
或equals
-但至少它描述了@ Mustafa-Kemal提到的“解决方法”需求的最可能原因,即使使用@ Vlad-Mihalcea提到的广泛使用的方法,也必须记住这一点。
注1:EntityManager::merge(...)
可能会更改(并且通常会更改)对象的内存地址,用于(我不保证)用于hashCode()的默认计算-请参见System.identityHashCode(Object x );有关更多信息。
注2:如果您使用自定义的hashCode方法,EntityManager::persist(...)
可能会更改用于hashCode计算的属性-是的,我在说的是主键,一个id,在这里很想用作hashCode :)