我有一个简单的班级角色:
@Entity @Table (name = "ROLE") public class Role implements Serializable { @Id @GeneratedValue private Integer id; @Column private String roleName; public Role () { } public Role (String roleName) { this.roleName = roleName; } public void setId (Integer id) { this.id = id; } public Integer getId () { return id; } public void setRoleName (String roleName) { this.roleName = roleName; } public String getRoleName () { return roleName; } }
现在,我想重写其方法equals和hashCode。我的第一个建议是:
public boolean equals (Object obj) { if (obj instanceof Role) { return ((Role)obj).getRoleName ().equals (roleName); } return false; } public int hashCode () { return id; }
但是,当我创建新的Role对象时,其id为null。这就是为什么我对hashCode方法实现有一些问题。现在,我可以简单地返回,roleName.hashCode ()但是如果没有RoleName字段,该怎么办?我几乎可以肯定,组成更复杂的示例并不难,而通过返回其字段之一的hashCode不能解决该示例。
roleName.hashCode ()
因此,我想查看一些指向相关讨论的链接,或者听听您解决此问题的经验。谢谢!
鲍尔和金的书《 Java持久性与Hibernate》 建议不要将键字段用于equals和hashCode。他们建议您应该选择对象的业务密钥字段(如果没有人工密钥),然后使用它们来测试相等性。因此,在这种情况下,如果角色名称不是必填字段,则可以找到必要的字段并结合使用。在您发布的代码中,除了id之外,您还拥有角色名,角色名就是我想要的。
以下是第398页的引文:
我们认为,基本上每个实体类都应该具有 一些 业务密钥,即使它包含了该类的所有属性(这对于某些不可变的类也是适当的)。业务密钥是用户唯一标识特定记录的东西,而代理密钥是应用程序和数据库使用的东西。 业务密钥相等性 意味着equals()方法仅比较构成业务密钥的属性。这是避免先前提出的所有问题的理想解决方案。唯一的缺点是,首先需要额外的思想来识别正确的业务密钥。无论如何,都需要付出这种努力。如果您的数据库必须通过约束检查确保数据完整性,则标识任何唯一键非常重要。
我们认为,基本上每个实体类都应该具有 一些 业务密钥,即使它包含了该类的所有属性(这对于某些不可变的类也是适当的)。业务密钥是用户唯一标识特定记录的东西,而代理密钥是应用程序和数据库使用的东西。
业务密钥相等性 意味着equals()方法仅比较构成业务密钥的属性。这是避免先前提出的所有问题的理想解决方案。唯一的缺点是,首先需要额外的思想来识别正确的业务密钥。无论如何,都需要付出这种努力。如果您的数据库必须通过约束检查确保数据完整性,则标识任何唯一键非常重要。
我用来构造equals和hashcode方法的一种简单方法是创建一个toString方法,该方法返回“业务键”字段的值,然后在equals()和hashCode()方法中使用它。澄清:这是一种懒惰的方法,适用于我不关心性能的情况(例如,在内部为皱纹的内部webapp中),如果预计性能会成为问题,请自己编写方法或使用IDE的代码生成工具。