Grails 来自Mixin的公共域列的公共beforeInsert和beforeUpdate方法

Grails 来自Mixin的公共域列的公共beforeInsert和beforeUpdate方法,grails,groovy,gorm,mixins,Grails,Groovy,Gorm,Mixins,我们公司使用的大多数域对象都有一些公共属性。它们表示创建对象的用户、上次更新对象的用户以及他们用来执行此操作的程序 为了对我的域类进行扩展,我想找到一些方法,在不干扰那些没有列的域类的情况下,向所有具有这些列的域类添加相同的beforeInsert和beforeUpdate逻辑 我希望使用具有自己的beforeInsert和beforeUpdate方法的。我知道 单元测试将表明,当以这种方式实现时,beforeInsert方法实际上没有被触发 旁注: 我也知道使用元类是可能的,但是我的好奇心战胜

我们公司使用的大多数域对象都有一些公共属性。它们表示创建对象的用户、上次更新对象的用户以及他们用来执行此操作的程序

为了对我的域类进行扩展,我想找到一些方法,在不干扰那些没有列的域类的情况下,向所有具有这些列的域类添加相同的beforeInsert和beforeUpdate逻辑

我希望使用具有自己的beforeInsert和beforeUpdate方法的。我知道

单元测试将表明,当以这种方式实现时,beforeInsert方法实际上没有被触发

旁注: 我也知道使用元类是可能的,但是我的好奇心战胜了我,我真的想看看mixin是否有效。请随时告诉我,这是更好的方法,我不应该混淆人们不应该混淆的地方。

仅供参考,groovy项目负责人强烈反对使用groovy.lang.Mixin。如果必须使用Mixin,那么应该使用grails.util.Mixin。关于你的mixin方法,我不喜欢的一点是,它隐式地、非强制地假设mixin的目标具有creator和updater属性

就我个人而言,我可能会使用普通的旧继承来实现这一点,例如

abstract class Audit {

    String creator
    String updater

    def beforeInsert() {
        this.creator = 'foo'
        this.updater = 'foo'
    }

    def beforeUpdate() {
        this.updater = 'bar'
    }

    static constraints = {
        creator nullable: false
        updater nullable: false
    }
}
任何需要审核的域类都将简单地扩展审核。另一种更可取的方法是使用抽象基类,而不是抽象基类,但要做到这一点,您需要使用相当新的Grails版本。

仅供参考,groovy项目负责人强烈反对使用groovy.lang.Mixin。如果必须使用Mixin,那么应该使用grails.util.Mixin。关于你的mixin方法,我不喜欢的一点是,它隐式地、非强制地假设mixin的目标具有creator和updater属性

就我个人而言,我可能会使用普通的旧继承来实现这一点,例如

abstract class Audit {

    String creator
    String updater

    def beforeInsert() {
        this.creator = 'foo'
        this.updater = 'foo'
    }

    def beforeUpdate() {
        this.updater = 'bar'
    }

    static constraints = {
        creator nullable: false
        updater nullable: false
    }
}

任何需要审核的域类都将简单地扩展审核。另一种更可取的方法是使用一个而不是一个抽象基类,但要做到这一点,您需要使用一个相当新的Grails版本。

您可以使用的事件总线使您的应用程序更加枯燥。该插件支持将侦听器添加到,并且它们可以应用于任何给定的类或接口实例。您还可以附加多个侦听器并编写更简洁的单元测试

如果要共享某些跨域逻辑,则它们必须实现接口,然后使用以下方法创建服务:

// domainService.groovy

@grails.events.Listener(namespace='gorm')
def beforeInsert(DomainInterface domain){
    domain.creator = 'foo'
    domain.updater = 'bar'

    // If the method returns false, then domain.save() won't be called. 
}

您可以使用的事件总线使您的应用程序更加干燥,而不是混搭。该插件支持将侦听器添加到,并且它们可以应用于任何给定的类或接口实例。您还可以附加多个侦听器并编写更简洁的单元测试

如果要共享某些跨域逻辑,则它们必须实现接口,然后使用以下方法创建服务:

// domainService.groovy

@grails.events.Listener(namespace='gorm')
def beforeInsert(DomainInterface domain){
    domain.creator = 'foo'
    domain.updater = 'bar'

    // If the method returns false, then domain.save() won't be called. 
}

继承对我来说似乎是合理的。我将把src/groovy中的mixin更改为抽象类并使用extenses。我很想使用traits,但我们还没有达到最新的Grails。此外,我在一次编辑中也注意到了这一点,但要使其起作用,您需要一个beforeValidate方法来填充所需的字段creator和updater,或者beforeInsert和beforeUpdate从未被调用。正如更新一样,继承会在对域进行单元测试时产生一些问题,我尚未解决这些问题。。。主要是因为这里的示例隐藏了我实际实现的复杂性。请参阅上面链接的摘要:Groovy的@Delegate方法就是答案。我想Traits会更漂亮,但现在,我很高兴使用@Delegate注释引入一个带有beforeValidate方法的类。我将把src/groovy中的mixin更改为抽象类并使用extenses。我很想使用traits,但我们还没有达到最新的Grails。此外,我在一次编辑中也注意到了这一点,但要使其起作用,您需要一个beforeValidate方法来填充所需的字段creator和updater,或者beforeInsert和beforeUpdate从未被调用。正如更新一样,继承会在对域进行单元测试时产生一些问题,我尚未解决这些问题。。。主要是因为这里的示例隐藏了我实际实现的复杂性。请参阅上面链接的摘要:Groovy的@Delegate方法就是答案。我想Traits会更漂亮,但现在,我很高兴使用@Delegate注释引入一个带有beforeValidate方法的类。