等于grails中的域类

时间:2015-04-07 20:05:46

标签: grails gorm

以下等于代码返回域

的错误结果
boolean equals(o) {
  if (o == null) return false
  if (this.is(o)) return true
  getClass() == o.class && id == o.id
}

对于具有相同id的两个加载实体,返回false。 Id等于(DB中的一条记录)。但课程不一样。

实体 - 其他域中的字段。看起来GORM使用了一些包装类。

如何避免这种问题?

2 个答案:

答案 0 :(得分:0)

正如您所看到的,要求课程相同是非常严格的。使用instanceof通常更安全,例如

class Foo {
    boolean equals(o) {
        if (!o) return false
        if (is(o)) return true
        o instanceof Foo && id == o.id
    }
}

idequals中使用hashCode在域类中通常是一个坏主意,因为您无法比较持久类和非持久类。例如

class Foo {
    String name
    boolean equals(o) {
        if (!o) return false
        if (is(o)) return true
        o instanceof Foo && id == o.id
    }
}

使用这个课程,这会失败:

new Foo(name: 'foo').save()
assert Foo.findByName('foo') == new Foo(name: 'foo')

但是所有重要的类数据(在这种情况下只是name属性)在两种情况下都是相同的。

更糟糕的是,假设你创建一个同样被破坏的hashCode方法,如果你将一个非持久化实例添加到基于哈希的集合(例如HashSet)然后保存它,它的{{ 1}}将从null更改为某个long值,因此其hashcode值也将更改。这将导致实例在集合中“丢失”。

答案 1 :(得分:0)

GormInstanceApi中的特殊方法在哪里

/**
 * Proxy aware instanceOf implementation.
 */
boolean instanceOf(D o, Class cls) {
    if (o instanceof EntityProxy) {
        o = (D)((EntityProxy)o).getTarget()
    }
    return o in cls
}

使用此方法解决了问题