Hibernate javassist proxies和`Object#equals`

Sky*_*ker 10 java orm hibernate javassist

#equals在Java中为UDT 提供实现时,其中一个条件是传递的参数对象必须是当前类的实例,否则我们会失败 - 快速return false查看Effective Java(EJ2).但是,在使用Hibernate 4时,由于延迟加载,这种#equals情况会失败,因此最终会导致javassist代理实例.什么是克服这个问题的最佳选择?我能想到的几个选择是:

  • 扩展equals实现以考虑代理案例.缺点:可维护性收费,对Hibernate代理基础架构的硬连线依赖,hacky,实体或域模型应该与所使用的ORM无关,即因为它们可能在不需要ORM的情况下重用,例如Swing UI.
  • 在调用之前检查它是否是代理equals.缺点:并非总是可能,即处理集合和隐式调用equals,例如Map.
  • 避免使用延迟加载.缺点:在所有用例中都不合理也没有效率.

UPDATE

再次回顾EJ2我相信以下内容适用于所有场景(Type-Type,Type-Proxy,Proxy-Type和Proxy-Proxy),但正如下面的一条评论中所指出的,如果将Type与之比较,它可能永远循环完全不同的类型,例如Person.equals(Employee),两者都使用相同的等于EJ2标准.

    if (this.getClass() != anObject.getClass())
    {
        return anObject.equals(this);
    }
Run Code Online (Sandbox Code Playgroud)

Wil*_*Wit 11

我偶然发现了同样的问题.我修复的方法是改变.equals方法.

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!getClass().isAssignableFrom(obj.getClass()))
        return false;
    AbstractEntity other = (AbstractEntity) obj;
    if (getId() == null) {
        if (other.getId() != null)
            return false;
    } else if (!getId().equals(other.getId()))
        return false;
    return true;
Run Code Online (Sandbox Code Playgroud)

诀窍是不要将类比较相同但使用isAssignableFrom-method.另一个技巧是不使用直接属性(other.id),但使用get-method(other.getId())


DHa*_*sen 7

我没有评论Willem de Wit答案的声誉.比我需要发布一个新的答案.

要解决djechelon的问题,你应该替换这一行:

if (!getClass().isAssignableFrom(obj.getClass()))
Run Code Online (Sandbox Code Playgroud)

对于

if ( !obj.getClass().isAssignableFrom(getClass()) && !getClass().isAssignableFrom(obj.getClass()) )
Run Code Online (Sandbox Code Playgroud)

然后,您将确保equals适用于所有方案(Type-Type,Type-Proxy,Proxy-Type和Proxy-Proxy).

我也没有声誉来表达你的答案.我太悲惨了!