等于 grails 中的域 class
Equals for domain class in grails
以下等于代码 returns 域的错误结果
boolean equals(o) {
if (o == null) return false
if (this.is(o)) return true
getClass() == o.class && id == o.id
}
对于两个具有相同 ID 的已加载实体 return false。 Id 等于(数据库中的一条记录)。但是类不一样。
实体 -- 另一个域中的字段。看起来 GORM 使用了一些包装器 类.
如何避免此类问题?
如您所见,要求 class 相同过于严格。使用 instanceof
通常更安全,例如
class Foo {
boolean equals(o) {
if (!o) return false
if (is(o)) return true
o instanceof Foo && id == o.id
}
}
在 equals
或 hashCode
中使用 id
在领域 class 中通常不是一个好主意,因为您无法比较持久性和非持久性 class是的。例如
class Foo {
String name
boolean equals(o) {
if (!o) return false
if (is(o)) return true
o instanceof Foo && id == o.id
}
}
有了这个 class,这会失败:
new Foo(name: 'foo').save()
assert Foo.findByName('foo') == new Foo(name: 'foo')
但是所有重要的 class 数据(在本例中只是 name
属性)在这两种情况下都是相同的。
更糟糕的是,假设您创建了一个同样损坏的 hashCode
方法,如果您将一个非持久实例添加到基于散列的集合(例如 HashSet
)然后保存它,它的id
将从 null 变为某个 long 值,其哈希码值也将如此。这将导致该实例成为集合中的 "lost"。
GormInstanceApi中的特殊方法在哪里
/**
* Proxy aware instanceOf implementation.
*/
boolean instanceOf(D o, Class cls) {
if (o instanceof EntityProxy) {
o = (D)((EntityProxy)o).getTarget()
}
return o in cls
}
使用这个方法解决了问题
以下等于代码 returns 域的错误结果
boolean equals(o) {
if (o == null) return false
if (this.is(o)) return true
getClass() == o.class && id == o.id
}
对于两个具有相同 ID 的已加载实体 return false。 Id 等于(数据库中的一条记录)。但是类不一样。
实体 -- 另一个域中的字段。看起来 GORM 使用了一些包装器 类.
如何避免此类问题?
如您所见,要求 class 相同过于严格。使用 instanceof
通常更安全,例如
class Foo {
boolean equals(o) {
if (!o) return false
if (is(o)) return true
o instanceof Foo && id == o.id
}
}
在 equals
或 hashCode
中使用 id
在领域 class 中通常不是一个好主意,因为您无法比较持久性和非持久性 class是的。例如
class Foo {
String name
boolean equals(o) {
if (!o) return false
if (is(o)) return true
o instanceof Foo && id == o.id
}
}
有了这个 class,这会失败:
new Foo(name: 'foo').save()
assert Foo.findByName('foo') == new Foo(name: 'foo')
但是所有重要的 class 数据(在本例中只是 name
属性)在这两种情况下都是相同的。
更糟糕的是,假设您创建了一个同样损坏的 hashCode
方法,如果您将一个非持久实例添加到基于散列的集合(例如 HashSet
)然后保存它,它的id
将从 null 变为某个 long 值,其哈希码值也将如此。这将导致该实例成为集合中的 "lost"。
GormInstanceApi中的特殊方法在哪里
/**
* Proxy aware instanceOf implementation.
*/
boolean instanceOf(D o, Class cls) {
if (o instanceof EntityProxy) {
o = (D)((EntityProxy)o).getTarget()
}
return o in cls
}
使用这个方法解决了问题