首先考虑代码段
public class Employee
{
private Integer id;
private String firstname;
private String lastName;
private String department;
// public getters and setters here, i said PUBLIC
}
我创建了2个具有相同ID的对象,其余所有字段也相同。
Employee e1 = new Employee();
Employee e2 = new Employee();
e1.setId(100);
e2.setId(100);
//Prints false in console
System.out.println(e1.equals(e2));
整个问题从这里开始 在实时应用程序中,必须返回true。
因此,每个人都知道存在一个解决方案(实现equals()和hashcode())
public boolean equals(Object o) {
if(o == null)
{
return false;
}
if (o == this)
{
return true;
}
if (getClass() != o.getClass())
{
return false;
}
Employee e = (Employee) o;
return (this.getId() == e.getId());
}
@Override
public int hashCode()
{
final int PRIME = 31;
int result = 1;
result = PRIME * result + getId();
return result;
}
现在,像往常一样:
Employee e1 = new Employee();
Employee e2 = new Employee();
e1.setId(100);
e2.setId(100);
//Prints 'true' now
System.out.println(e1.equals(e2));
Set<Employee> employees = new HashSet<Employee>();
employees.add(e1);
employees.add(e2);
//Prints ofcourse one objects(which was a requirement)
System.out.println(employees);
我正在阅读这篇优秀的文章Don't Let Hibernate Steal Your Identity。但有一件事我完全没理解。上面讨论的整个问题及其解决方案和链接文章在2个Employee对象id相同时处理问题。
考虑 的私人设定者, 生成器类生成的ID字段< hbm.xml 中提供了/ em> 。一旦我开始持久化Employee对象( ,我决不能改变id ),我发现不需要实现equals和hashcode方法。我确信我错过了一些东西,因为我的直觉说当一个特定的概念在网络上旋转太多时,为了避免一些常见错误,它必须始终摆在你面前?当我有一个id字段的私人设置器时,我还需要实现这两种方法吗?
答案 0 :(得分:1)
使用生成的标识符进行相等操作not a good idea,您应该使用自然的商家密钥,因为它在所有entity state transitions中都是一致的。
如果在保留实体之前将实体添加到HashSet
,则在保留实体并刷新会话后,您将无法检索实体。那是因为id改变了,所以hashCode也改变了。
在您的示例中,您一直使用assigned
标识符在您保留实体时不会更改。当您使用生成的标识符(IDENTITY,SEQUENCE)时会出现问题,因为transient
实体状态将具有null
id,而persisted
实体状态将具有not-null
} id(在同一个对象引用的生命周期内发生,并且equals / hashCode要求要求这些检查在不显式更改对象状态的情况下不会产生不同的结果)。在你的情况下,实际的实体状态不会改变,它只是当实体被持久化时改变的id。