假设我们有以下JPA实体:
class Parent {
@Id
private Long id;
}
class Child {
@Id
private Long id;
@Column
private String name;
@ManyToOne(fetch = FetchType.LAZY)
private Parent parent;
}
假设Child可以通过Parent上的名称唯一标识(两者的组合)。因此,Parent和name可以被视为Child的业务密钥。
我现在不确定在类Child上实现equals(和hashCode)的最佳方法是什么。
引用应用程序的ID
由于将加载Application代理并在代理上设置其id,因此不会初始化Application实体本身:
public boolean equals (Object o) { //null check, instanceof check ... return new EqualsBuilder().append(getName(), other.getName()) .append(getParent().getId(), other.getParent().getId()) .isEquals();
}
这可以解决问题,但我也看到了一些缺点。首先(次要),对父母进行额外的非空检查可能是可取的,这使得你的等于方法更少复合 接下来(不太小),这将需要hibernate来访问属性而不是字段;所以,我需要在getter上而不是在字段上设置注释。这是我个人可以忍受的事情,但当前项目的习惯是将注释放在字段级别上。
请勿使用引用的实体来评估相等性
好的,但我需要别的东西。我不想使用Child(不良做法)的id,它只留下一个选项:为此使用单独的属性,如UUID。我没有反对UUID的使用,但当然只有在没有其他选择的情况下才会使用。
我的问题是:
答案 0 :(得分:3)
另一种可能性是将另一个包含外键的字段添加到父节点,然后可以在equals和hashCode方法中使用它而无需获取引用的实体:
@Column(name="parent_id", insertable=false, updatable=false)
private String parentId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="parent_id")
private Parent parent;
答案 1 :(得分:0)
如果您可以获取EntityManagerFactory(如果您可以获取EntityManager,EntityManager.getEntityManagerFactory()是一种方法),另一种获取父ID的方法是:
emf.getPersistenceUnitUtil().getIdentifier(parent);
但是你仍然需要空检查。