首先,考虑一下代码段
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);
我正在阅读这篇出色的文章,“不要让休眠模式窃取您的身份”。但是有一件事我没有完全理解。当2个Employee对象ID相同时,上面讨论的整个问题及其解决方案以及链接的文章都在解决这些问题。
考虑一下我们是否有一个专用的id设置器,其id字段由hbm.xml中提供的generator类生成。一旦我开始保留Employee对象(并且绝不能更改id),我便无需实现equals和hashcode方法。我确信我会丢失一些东西,因为我的直觉说,当某个特定概念在网络上旋转过多时,为了避免某些常见错误,它一定总是摆在您面前吗?当我有一个ID字段的专用设置器时,是否仍需要实现这两种方法?
如果您的实体定义了自然业务密钥,则应将其用于equals和hashCode,如本文所述。自然标识符或业务密钥在所有实体状态转换之间都是一致的,因此,当JPA实体状态更改(例如,从NEW到MANAGED到DETACHED)时,hashCode不会更改。
在您的示例中,您使用的是assigned
标识符,当您保留实体时,标识符不会改变。
但是,如果您没有自然标识符,并且生成了PRIMARY KEY(例如IDENTITY,SEQUENCE),则可以实现equals和hashCode,如下所示:
@Entity
public class Book implements Identifiable<Long> {
@Id
@GeneratedValue
private Long id;
private String title;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Book))
return false;
Book other = (Book) o;
return id != null &&
id.equals(other.getId());
}
@Override
public int hashCode() {
return 31;
}
//Getters and setters omitted for brevity
}
实体标识符可用于equals
和hashCode,但前提是hashCode
返回值始终都返回相同的值。这听起来很可怕,因为它违反了在HashSet
或中使用多个存储桶的目的HashMap
。
但是,出于性能原因,您应始终限制集合中存储的实体数量。您绝对不应在中获取数千个实体,@OneToMany
Set
因为与使用单个哈希存储桶相比,数据库方面的性能损失要高多个数量级。
之所以使用此版本的equals
和,hashCode
是因为该hashCode
值不会从一个实体状态更改为另一种实体状态,并且仅当标识符不是时才检查标识符null
。
有关此主题的更多详细信息,请参阅本文。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句