使用引用的ManyToOne实体实现equals / hashCode

时间:2011-04-21 08:52:34

标签: java hibernate jpa identity

假设我们有以下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的使用,但当然只有在没有其他选择的情况下才会使用。

我的问题是:

  1. 我错过了一个选项吗?
  2. 在您看来,建议的做法是什么?

2 个答案:

答案 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);

但是你仍然需要空检查。