来自 Mixin 的通用域列的通用 beforeInsert 和 beforeUpdate 方法

Common beforeInsert and beforeUpdate methods from Mixin for common domain columns

我们公司使用的大多数领域对象都有一些共同的属性。这些代表创建对象的用户、最后更新对象的用户以及他们用来执行此操作的程序。

为了 DRY 退出我的域 类,我想找到一些方法将相同的 beforeInsert 和 beforeUpdate 逻辑添加到具有这些列的所有域 类不干涉那些不干涉的人。

喜欢的方式是使用Mixin with its own beforeInsert and beforeUpdate methods. I know you can use Mixins on domain classes

package my.com

import my.com.DomainMixin

@Mixin(DomainMixin)
class MyClass {
    String foo
    String creator
    String updater

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


package my.com
class DomainMixin {
    def beforeInsert() {
        this.creator = 'foo'
        this.updater = 'foo'
    }

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

单元测试表明,以这种方式实现时,beforeInsert 方法实际上并未被触发。

旁注: 我也知道可以 to add the methods in a BootStrap.groovy file 使用 metaClass,但我的好奇心战胜了我,我真的很想看看 mixin 是否有效。请随时告诉我,这是更好的方法,我不应该混淆人们不应该混淆的地方。

仅供参考,强烈建议不要使用 groovy.lang.Mixin(Groovy 项目负责人)。如果你必须使用 mixins,你应该使用 grails.util.Mixin 代替。我不喜欢你的 mixin 方法的一件事是隐含的和非强制的假设,即 mixin 的目标具有 creatorupdater 属性

就个人而言,我可能会为此使用普通的继承,例如

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
    }
}

任何需要审核的域 classes 只需扩展 Audit。另一种(也是更可取的)方法是使用 trait 而不是抽象基础 class,但您需要使用相当新的 Grails 版本才能做到这一点。

您可以使用 Grails Platform plugin to make your app more DRY. The plugin supports adding listeners to GORM eventsEvent Bus 而不是混合,它们可以应用于任何给定的 class 或接口实例。您还可以附加多个侦听器并编写更简洁的单元测试。

如果你想跨域共享一些逻辑,他们必须实现一个接口,然后使用以下方法创建一个服务:

// 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. 
}