Hibernate等于和代理 [英] Hibernate equals and proxy

查看:107
本文介绍了Hibernate等于和代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个BaseEntity,它抽象了id和版本属性。这个类还实现了基于PK(id)属性的hashcode和equals。

  BaseEntity {

Long id;
长版;

public int hashCode(){
final int prime = 31;
int result = 1;
result = prime * result +((id == null)?0:id.hashCode());
返回结果;

$ b $ 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;
返回true;
}


}

现在两个实体A和B扩展BaseEntity,如下所示:

  A扩展BaseEntity {
`B b`
B getB ){return b;)
void setB(B b){this.b = b;}
}

B扩展BaseEntity {
}

对象b1;
对象a1;
a1.set(b1);
session.save(a1)//级联保存;

关闭会话
使用lazy b加载a并尝试a1.getB()。equals b1)给出了假
,但如果我与a1.getB()。getId()。equals(b1.getId())比较,则会给出真正的奇怪!
i认为这是因为java协助代理对象,无论如何解决这个问题?

解决方案

为了能够懒惰,加载 ab 关联,Hibernate设置 a b >到代理。代理是扩展B的类的一个实例,但不是B.因此,比较非代理B实例和代理B实例时,equals()方法总是失败,因为它比较了两个对象的类:

  if(getClass()!= obj.getClass())
return false;

对于Hibernate实体,您应该将其替换为

  if(!(obj instanceof B)){
return false;
}

另外,请注意


  • Hibernate建议不要使用 c> equals()和 hashCode() ID,而是通过使用自然标识符。使用ID实现它可能会导致问题,因为实体在保存并生成标识之前没有ID

  • 使用实体继承时,问题更加严重。假设B是两个子实体B1和B2的超类。在加载之前,Hiberante无法知道哪个类型(B1或B2)是 a.b 。因此 a.b 将被初始化为一个代理,该代理是B的子类,但不是B1或B2的子类。因此,应该在B中实现 hashCode() equals()方法,但不会在B1和B2中重写。如果两个B实例是B的实例并且具有相同的标识符,则应将它们视为相等。


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;
}


}

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;

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?

解决方案

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;

In the case of Hibernate entities, you should replace this with

if (!(obj instanceof B)) {
    return false;
}

Also, note that

  • Hibernate recommends not implementing equals() and hashCode() 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. So a.b will be initialized to a proxy which is a subclass of B, but is not a subclass of B1 or B2. So the hashCode() and equals() 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆