【问题标题】:How to execute a script before database schema generation in Grails?如何在 Grails 中生成数据库模式之前执行脚本?
【发布时间】:2016-11-08 17:32:48
【问题描述】:

我正在使用 Grails 2.5.5。在我的引导程序中,我为 String 注册了一个静态方法来生成 UUID:

String.metaClass.static.uuid = { ->
  java.util.UUID.randomUUID().toString()
}

在我的域类上,我想使用该方法来初始化一个 uid 字段:

class Organization {

   String uid = String.uuid()
   ...
}

问题是当我运行我的 Grails 应用程序时,它会生成数据库模式,这似乎发生在执行 Bootstrap 之前。生成创建域类的实例,但 String.uuid() 尚未注册,所以我得到了 MissingMethodException。

如何创建一个在数据库架构生成之前运行的脚本,以便在其中注册我的所有方法,以便它们在架构生成时可用?

仅供参考:完整的堆栈跟踪

2016-11-08 17:11:23,638 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener  - Error initializing the application: Error creating b
ean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreatio
nException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'se
ssionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invoc
ation of init method failed; nested exception is org.hibernate.MappingException: Could not get constructor for org.codehaus.groovy.grails.orm.hib
ernate.persister.entity.GroovyAwareSingleTableEntityPersister
Message: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.
beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while
setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with nam
e 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Could not get constructor for org.codeh
aus.groovy.grails.orm.hibernate.persister.entity.GroovyAwareSingleTableEntityPersister
    Line | Method
->>  262 | run       in java.util.concurrent.FutureTask
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run       in java.lang.Thread
Caused by BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while sett
ing bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 's
essionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Could not get constructor for org.codehaus.
groovy.grails.orm.hibernate.persister.entity.GroovyAwareSingleTableEntityPersister
->>  262 | run       in java.util.concurrent.FutureTask
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run       in java.lang.Thread
Caused by BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibern
ate.MappingException: Could not get constructor for org.codehaus.groovy.grails.orm.hibernate.persister.entity.GroovyAwareSingleTableEntityPersist
er
->>  262 | run       in java.util.concurrent.FutureTask
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run       in java.lang.Thread
Caused by MappingException: Could not get constructor for org.codehaus.groovy.grails.orm.hibernate.persister.entity.GroovyAwareSingleTableEntityP
ersister
->>  262 | run       in java.util.concurrent.FutureTask
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run       in java.lang.Thread
Caused by InstantiationException: could not instantiate test object : com.cabolabs.ehrserver.query.Query
->>  262 | run       in java.util.concurrent.FutureTask
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run       in java.lang.Thread
Caused by InvocationTargetException: null
->>  262 | run       in java.util.concurrent.FutureTask
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run       in java.lang.Thread
Caused by MissingMethodException: No signature of method: static java.lang.String.uuid() is applicable for argument types: () values: []
Possible solutions: wait(), trim(), dump(), find(), wait(long), is(java.lang.Object)
->>   28 | <init>    in com.cabolabs.ehrserver.query.Query
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|    262 | run       in java.util.concurrent.FutureTask
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run . . . in java.lang.Thread

【问题讨论】:

    标签: grails grails-orm


    【解决方案1】:

    我强烈建议您为您的功能创建一个插件,这样您就可以使用插件的loadBefore 功能来确保在其他插件之前添加您的功能。 Grails 关于插件的文档详细描述了如何Control Load Order

    【讨论】:

    • 在我的情况下,这将类似于 loadBefore = [ 'domain'] ?文档似乎没有显示 loadBefore 的所有可能值。
    • 实际上,我认为您想要loadBefore = ['database-migration'],以便您的插件在数据库迁移插件之前加载。我不是 100% 确定插件名称,但快速浏览一下源代码让我认为上述内容是正确的。
    猜你喜欢
    • 2017-11-01
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多