Grails 3 @Delegate 表示法,使用域对象

Posted

技术标签:

【中文标题】Grails 3 @Delegate 表示法,使用域对象【英文标题】:Grails 3 @Delegate notation, using a domain object 【发布时间】:2016-04-10 20:32:40 【问题描述】:

在 Grails 2.4.4 中,我们将类用作域对象的包装器。

它们看起来像这样:

class Foo 
  @Delegate
  OurDomainClass ourDomainClass
  ...


这行得通,但是当尝试在 Grails 3.0.11 下编译时,我们得到了这个:

> Foo.groovy: 14: Can't have an abstract method in a non-abstract class.
> The class 'Foo' must be declared abstract or the method
> 'org.springframework.validation.Errors
> org_grails_datastore_gorm_GormValidateable__errors$get()' must be
> implemented.  @ line 14, column 1.    class Foo     ^

删除@Delegate 注释将使编译通过,但对底层类的方法的调用显然不起作用。

有没有办法解决这个问题或实现相同的行为并让它在 Grails 3 下通过编译?

【问题讨论】:

您是否尝试将@Validatable 添加到您的包装器中? 在 grails 3.x 命令实现接口 Validatable 而不是 @Validatable... 请原谅我的无知,但是用类包装域背后的想法是什么?是否将 DAO 层与视图层解耦,这样视图对数据库结构的了解为零?如果是这样,您的服务层是否总是返回 Wrapper 对象?你的插入和更新呢?您的 Service 层是否始终接收 Wrapper 对象? @Viriato - 这样域类本身就不会被一堆方法弄得杂乱无章 - 它本质上被用作装饰器。 【参考方案1】:

static hasMany = []static hasOne = [] 不会做这项工作吗?当然,包装器也可以是领域类。

【讨论】:

【参考方案2】:

您可以通过更改包装类来实现 GORM 特征来解决此问题:

class Foo implements GormValidateable, DirtyCheckable, Validateable 
    @Delegate
    OurDomainClass ourDomainClass
    ...

我更进一步,创建了自己的界面:

class Foo implements GormDelegateHack 
    @Delegate
    OurDomainClass ourDomainClass
    ...


interface GormDelegateHack extends GormValidateable, DirtyCheckable, Validateable 

我针对 grails-data-mapping 提交了 issue #856,尽管它可能是 Groovy bug。

【讨论】:

【参考方案3】:

@timbonicus 的解决方案适用于 Grails 3,但在 Grails 4 上失败并出现多个错误。

最终将 @Delegate 类更改为 Groovy traits 作为替代方案。它仍然是分开的,因为特征支持多重继承和实现的方法。此外,不需要像 embeddedhasManyhasOne 那样向对象添加另一个调用。

trait OurDomainClass 

trait OurOtherDomainClass 

class Foo implements OurDomainClass, OurOtherDomainClass 

如果你正在创建插件,你可以add methods at compile time with traits。

【讨论】:

以上是关于Grails 3 @Delegate 表示法,使用域对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Grails 3 中使用外部 .groovy 配置文件

向 Grails 中的对象添加方法并使其全局可用

Grails 3 - f:table - 如何显示相关类的属性

Grails 3 - 资源插件

Grails 2.5.1 to Grails 3.3.2

使用 Grails 3 配置 CORS