Grails 2.5.4中的GORM触发模式

时间:2016-06-25 06:15:45

标签: grails triggers gorm

我想在Grails中为我的域类实现Trigger个对象的概念。 Grails允许我在我的域类中将beforeInsert()之类的方法定义为handle insert, update and delete events,类似于SQL数据库具有数据库触发器概念的方式。但是为了区分问题,我想将所有触发逻辑移到域类之外。

理想情况下,我可以在我的域类中定义一个static触发器类列表,然后在beforeInsert()方法中迭代这些类。示例代码如下所示。

static beforeInsertTriggers = [AccountNameTrigger, AccountDumpTrigger]

def beforeInsert() {
    for (Class<Trigger> triggerClass : beforeInsertTriggers) {
        triggerClass.newInstance().using(this).execute()
    }
}

我创建了一个sample Grails 2.5.4 project on GitHub来说明我正在尝试做什么。但问题是触发器字面上是独立的逻辑孤岛,没有自动装配服务的能力。如何更好地设置此Trigger模式或类似的模式?所以我可以将服务和其他bean自动装入Trigger实例?

我也在努力保持设计的简洁性和可读性。

  • 避免使用与数据模型无关的字段和属性来混淆域类。对我来说,这意味着域类中没有自动装配的bean。
  • 使用触发器类名称(或bean名称,如果需要)定义触发器列表。这可能过于理想化了,但是嘿......

对于它的价值,我的灵感部分也来自于Salesforce implements triggers作为独立代码的不同单位。

1 个答案:

答案 0 :(得分:0)

将您的触发器注册为Singleton Beans,您可以注入其他服务/ bean。您可以通过resources.groovy创建自定义bean。

让我们以AccountDumpTrigger为例。让我们做一个简单的改变:

package grails.domain.trigger.demo.triggers

import grails.domain.trigger.demo.Account
import org.codehaus.groovy.grails.commons.GrailsApplication

/**
 * Created by marty on 6/25/16.
 */
class AccountDumpTrigger extends AbstractTrigger<Account> {

    GrailsApplication grailsApplication

    @Override
    void execute() {
        println grailsApplication.isInitialised()
        println resource.dump()
    }
}

并在resources.groovy或插件的doWithSpring闭包中编码:

accountDumpTrigger(grails.domain.trigger.demo.triggers.AccountDumpTrigger) { bean ->
    bean.factoryMethod = 'getInstance'
    /*
     either refer each bean individually  or you can use:
     bean.autowire = "byType"
       OR
     bean.autowire = "byName"
    */
    grailsApplication = ref("grailsApplication")
}

在你的域名内:

static beforeInsertTriggers = [AccountDumpTrigger]

def beforeInsert() {
    for (Class<Trigger> triggerClass : beforeInsertTriggers) {
        triggerClass.instance.using(this).execute()
    }
}

而不是在beforeInsert中编写代码,您也可以通过注册AbstractPersistenceEventListener的实现来执行相同的操作。这样您就不必重复代码了。你也可以把它移到父类。