【问题标题】:How to use domain class methods on Utils or src/groovy?如何在 Utils 或 src/groovy 上使用域类方法?
【发布时间】:2016-03-21 11:32:42
【问题描述】:

我正在使用 grails 应用程序。我想执行get(),save(),delete(),findBy() 等方法并与 grails 应用程序的域相关联。当我在 Utils 或 src/groovy 包中执行 Domain.get() 方法时,出现以下错误。

Caught: java.lang.IllegalStateException: Method on class [Domain Class] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.

java.lang.IllegalStateException: Method on class [Domain Class] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.

任何人都可以帮助我如何在 Utils 或 src/groovy 类中使用域类方法?

【问题讨论】:

  • 您需要为您的问题提供更多背景信息。你在哪里使用src/groovy 中的课程?是什么在调用它们,进而调用您的域类?尝试为您的问题提供更多详细信息,并提供您正在做的实际示例,您会得到更好的答案。
  • import com.chatportal.ShiroUser class ChatUtility { static main(args) { def chatUtility = new ChatUtility() chatUtility?.display(1) } def display(def id){ println "ChatUtility 聊天用户:"+ShiroUser.get(id) } }
  • 错误是发生在测试中还是正在运行的应用程序中?
  • @Piyush 你能指出这个错误是在什么情况下发生的吗?它发生在测试期间吗?如果没有,报告错误的域 lass 是否有什么特别之处(用 Java 编写?从插件中提取?映射到 hibernate cfg 文件中?有什么非标准的吗?)
  • 如果没有更多上下文,您所询问的场景并不十分清楚。

标签: java grails grails-orm grails-2.0 grails-domain-class


【解决方案1】:

此错误是由于与尚未在 GORM 中正确注册的 GORM 实体交互引起的。该错误与发起交互的位置无关(src/groovy、grails-app/services/ 等...)。

并非总是如此,但大多数情况下,此错误发生在实体类型尚未向 GORM 注册的测试环境中。

在https://github.com/jeffbrown/illegalaccessgorm 上查看该项目。该项目包含以下内容。

域类:

// grails-app/domain/demo/Person.groovy
package demo

class Person {
    String name
}

一项服务:

// grails-app/services/demo/HelperService.groovy
package demo

class HelperService {

    int getNumberOfPeople() {
        Person.count()
    }
}

一个实用类:

// src/groovy/demo/SomeHelper.groovy
package demo

class SomeHelper {
    int getNumberOfPeople() {
        Person.count()
    }
}

服务的单元测试:

// test/unit/demo/HelperServiceSpec.grovy
package demo

import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(HelperService)
@Mock(Person)
class HelperServiceSpec extends Specification {


    void "test gorm method"() {
        expect:
        service.numberOfPeople == 0
    }
}

实用程序类的单元测试:

// test/unit/demo/SomeHelperSpec.groovy
package demo

import spock.lang.Specification

@Mock(Person)
class SomeHelperSpec extends Specification {

    void "test gorm method"() {
        given:
        def helper = new SomeHelper()

        expect:
        helper.numberOfPeople == 0
    }
}

这两项测试都通过了。如果您从其中任何一个中删除 @Mock(Person),测试将失败并显示以下内容:

java.lang.IllegalStateException: Method on class [demo.Person] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.

如果问题发生在测试以外的某个上下文中,那么了解有关上下文的更多信息会很有帮助。其他可能的嫌疑人是由于某种原因未正确初始化的 Java 实体,在某些情况下,从插件引入的域类可能会出现问题。

此外,了解您使用的 Grails 版本可能是相关的。

我希望一切都有意义。

【讨论】:

    【解决方案2】:

    您不应在 src/groovy 或 utils 内使用域类。您应该为此使用服务。查看best practises for Grails architecture:

    域

    • 倾向于将模型领域特定的逻辑放在其自己的领域中。适用于具有少量依赖项的单个域的任何内容都应该放在其域类中。但请使其仅限于特定于该域的逻辑 - 处理一组域的更复杂的业务逻辑属于一项服务。
    • 要重用常见的部分查询或分解复杂的逻辑,请使用命名查询并根据需要将它们链接在一起,就像通常链接 jQuery 函数调用一样。
    • 不要在域文件夹中混合任何其他常见的实用程序类或值对象,而是可以将它们放在 src/groovy 中。如果这些类需要支持验证,可以使用@Validateable 对其进行注释。

    如果您还想这样做,请查看this FAQ:

    import org.codehaus.groovy.grails.commons.ApplicationHolder
    //…
    def book = ApplicationHolder.application.getClassForName("library.Book").findByTitle("Groovy in Action")
    

    【讨论】:

    • 我已经在 PROJECT/grails-app/domain/ 中创建了域类
    • @Michal_Szulc “你不应该在 src/groovy 或 utils 中使用域类。” - 从src/groovy 下定义的代码中引用域类是完全合理的做法。
    • 恕我直言,将所有域驱动的逻辑放入domain 并使用services 方法作为不同domain 方法和src/groovy 辅助方法之间的粘合剂会更干净。 controllers 将是一个流处理程序,当然还有其他帮助类留给src/groovy。为什么要混合呢?
    • 服务只是 grails 应用程序中的一种类。说服务是您应该与对域类的引用进行交互的唯一地方是没有意义的。有很多代码块不需要在服务中,其中一些代码块与域实例交互。
    • 即使有人同意您应该只与服务中的域实例交互的想法,但这并不能解决这里提出的问题。此问题不是由与服务外部的域类交互引起的。
    猜你喜欢
    • 2011-02-04
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 2023-01-04
    • 1970-01-01
    • 2016-01-30
    相关资源
    最近更新 更多