Java 中,每个类会继承 java.lang.Object 的 equals 方法(可覆盖),Grails的Domain类默认也继承了该方法,一般情况下,默认的 equals 方法能满足大多数要求,但是延迟加载的情况下,一些Domain实例加载后,被包装成了一个Proxy对象(类型为 x.y.Foobar_$$_xxx),此时默认的 equals 方法就会出现问题(比如调用列表的contains、remove等方法时)。而使用 Groovy 的注解  @EqualsAndHashCode,同样无法解决该问题,反而会造成其他的异常。
bropen.toolkit.utils.grails.BeanUtils 提供了一个 equals 的API来处理这种问题,并且在编译的时候将该方法注入到了每个Domain类的class文件中。默认情况下,该API会自动处理Proxy对象的问题,并比较ID来判断两个对象是否是同一个实例。
此外,还可以手动在Domain类前使用注解 @DomainEquals 实现:
- 比较除 id 外的其他字段,如下例所示,只要两个同类的Domain实例的 name 属性相同(或id相同),便认为两个对象相等:
 import bropen.toolkit.transform.DomainEquals
 
 @DomainEquals(includes = "name")
 class Foobar {
 String name
 }
 
 def b1 = new Foobar( name: "abc" )
 def b2 = new Foobar( name: "abc" )
 assert b1 == b2
 以外,includes 还可以设置为逗号分隔的多个字段,如下例:
 @DomainEquals(includes = "name, age")
 这样,对于联合主键的Domain类,可以使用本注解来生成 equals 方法,如:
 @DomainEquals(includes = "user, code")
 class Foobar {
 String user
 String code
 
 static mapping = {
 id composite: ["user", "code"]
 }
 }
- 比较 Domain 实例和 Map 对象,如下例所示,如果Domain实例的 name 属性和一个Map对象中的同名键值相同,则认为两个对象相等:
 @DomainEquals(compareMap = true, includes = "name")