Hibernate 等于和代理 [英] Hibernate equals and proxy
问题描述
我有一个抽象 id 和 version 属性的 BaseEntity.这个类还实现了基于 PK (id) 属性的 hashcode 和 equals.
I have one BaseEntity which abstracts id and version property. this class also implements hashcode and equals based on PK (id) property.
BaseEntity{
Long id;
Long version;
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseEntity other = (BaseEntity) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
现在两个Entity A和B扩展BaseEntity如下
now two Entity A and B extends BaseEntity as below
A extends BaseEntity{
`B b`
B getB(){return b;)
void setB(B b){this.b=b;}
}
B extends BaseEntity{
}
object b1;
object a1;
a1.set(b1);
session.save(a1) //cascade save;
关闭会话用惰性 b 加载 a 并尝试 a1.getB().equals(b1) 给出 false但如果我与 a1.getB().getId().equals(b1.getId()) 进行比较然后给出真奇怪!我认为是因为java辅助代理对象,无论如何要解决这个问题?
close session load a with lazy b and try a1.getB().equals(b1) gives false but if i compare with a1.getB().getId().equals(b1.getId()) then gives true strange!! i think it is because of java assist proxy object, anyway to resolve this?
推荐答案
为了能够延迟加载ab
关联,Hibernate在b
字段中设置了b
字段>a 到代理.代理是扩展 B 的类的实例,但不是 B.因此,将非代理 B 实例与代理 B 实例进行比较时,您的 equals() 方法将始终失败,因为它比较了两个对象的类:
To be able to lazy-load the a.b
association, Hibernate sets the b
field in a
to a proxy. The proxy is an instance of a class that extends B, but is not B. So, your equals() method will always fail when comparing a non-proxy B instance to a proxy B instance, because it compares the classes of both objects:
if (getClass() != obj.getClass())
return false;
对于 Hibernate 实体,您应该将其替换为
In the case of Hibernate entities, you should replace this with
if (!(obj instanceof B)) {
return false;
}
另外,请注意
- Hibernate 建议不要使用 ID 来实现
equals()
和hashCode()
,而是使用自然标识符.使用 ID 实现它可能会导致问题,因为实体在保存并生成 ID 之前没有 ID - 使用实体继承时,问题更严重.假设 B 是两个子实体 B1 和 B2 的超类.Hiberante 在加载之前无法知道
a.b
是哪种类型(B1 或 B2).所以a.b
将被初始化为一个代理,它是 B 的子类,但不是 B1 或 B2 的子类.所以hashCode()
和equals()
方法应该在 B 中实现,但不能在 B1 和 B2 中被覆盖.如果两个 B 实例是 B 的实例并且具有相同的标识符,则应将它们视为相等.
- Hibernate recommends not implementing
equals()
andhashCode()
by using the ID, but rather by using a natural identifier. Implementing it with IDs can cause problems because entities don't have an ID until they're saved and the ID is generated - When using entity inheritance, the problem is even worse. Suppose B is a superclass of two sub-entities B1 and B2. Hiberante can't know which type (B1 or B2) is
a.b
before loading it. Soa.b
will be initialized to a proxy which is a subclass of B, but is not a subclass of B1 or B2. So thehashCode()
andequals()
methods should be implemented in B, but not be overridden in B1 and B2. Two B instances should be considered equal if they're instances of B, and have the same identifier.
这篇关于Hibernate 等于和代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!