【发布时间】:2016-05-26 10:25:30
【问题描述】:
我无法从一对多关系中删除子实体。我设法将其缩小到 HashSet.contains() 只有在父(和子)实体被持久化后才返回 false。
以下代码
Parent parent = ParentFactory.parent();
Child child = ChildFactory.child();
parent.addChild(child);
System.out.println("contains? " + parent.getChilds().contains(child));
System.out.println("child.hashCode " + child.hashCode());
System.out.println("parent.child.hashCode " + parent.getChilds().iterator().next().hashCode());
System.out.println("equals? " + parent.getChilds().iterator().next().equals(child));
parentDao.save(parent);
System.out.println("contains? " + parent.getChilds().contains(child));
System.out.println("child.hashCode " + child.hashCode());
System.out.println("parent.child.hashCode " + parent.getChilds().iterator().next().hashCode());
System.out.println("equals? " + parent.getChilds().iterator().next().equals(child));
将打印:
contains? true
child.hashCode 911563320
parent.child.hashCode 911563320
equals? true
contains? false
child.hashCode -647032511
parent.child.hashCode -647032511
equals? true
我在similar questions 中读到,它可能是由重载而不是覆盖equals() 引起的,但我认为这不是问题,因为当我第一次检查contains() 时它会打印错误.顺便说一句,我用的是龙目岛的EqualsAndHashCode。
我的实体:
@Entity
@Table(name = "parents")
@Getter
@Setter
@EqualsAndHashCode
@ToString
public class Parent implements Serializable {
private static final long serialVersionUID = 6063061402030020L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Boolean isActive;
@OneToMany(fetch = EAGER, mappedBy = "parent", cascade = {ALL}, orphanRemoval = true)
private final Set<Child> childs = new HashSet<>();
public void addChild(Child child) {
this.childs.add(child);
child.setParent(this);
}
}
@Entity
@Table(name = "childs")
@Getter
@Setter
@EqualsAndHashCode(exclude = "parent")
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "parent")
public class Child implements Serializable {
private static final long serialVersionUID = 5086351007045447L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(fetch = EAGER)
@JoinColumn(name = "parentId_fk")
private Parent parent;
}
persist 后唯一改变的是child 的id,但child 和parent.child 都引用同一个实例,所以id 是相同的。 hashCode() 和 equals() 返回 true 证明了这一点。
为什么会这样?我该如何解决?
【问题讨论】:
-
如果哈希码发生变化,则基于哈希的集合将无法再找到对象。但是如果hashcode改变了,也意味着你有一个完全不同的对象,你不应该在hashset中使用它们。
-
保存前后
id的值是多少?由于这是自动分配的,我想这就是正在发生的变化,从而改变了哈希码。
标签: java hibernate jpa equals lombok