【问题标题】:How do I get the type (class) of a property of a Grails domain object?如何获取 Grails 域对象的属性的类型(类)?
【发布时间】:2010-11-01 17:16:07
【问题描述】:

我试图在 Grails 中动态创建域对象,但遇到了一个问题,即对于引用另一个域对象的任何属性,元属性告诉我它的类型是“java.lang.Object”而不是预期的类型。

例如:

class PhysicalSiteAssessment {
    // site info
    Site site
    Date sampleDate
    Boolean rainLastWeek
    String additionalNotes
    ...

是域类的开始,它引用另一个域类“Site”。

如果我尝试使用此代码(在服务中)动态查找此类的属性类型:

String entityName = "PhysicalSiteAssessment"
Class entityClass
try {
    entityClass = grailsApplication.getClassForName(entityName)
} catch (Exception e) {
    throw new RuntimeException("Failed to load class with name '${entityName}'", e)
}
entityClass.metaClass.getProperties().each() {
    println "Property '${it.name}' is of type '${it.type}'"
}

那么结果是它识别 Java 类,但不识别 Grails 域类。输出包含以下几行:

Property 'site' is of type 'class java.lang.Object'
Property 'siteId' is of type 'class java.lang.Object'
Property 'sampleDate' is of type 'class java.util.Date'
Property 'rainLastWeek' is of type 'class java.lang.Boolean'
Property 'additionalNotes' is of type 'class java.lang.String' 

问题是我想使用动态查找来查找匹配的对象,例如做一个

def targetObjects = propertyClass."findBy${idName}"(idValue)

propertyClass 是通过自省检索的,idName 是要查找的属性的名称(不一定是数据库 ID),idValue 是要查找的值。

一切都结束了:

org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: static java.lang.Object.findByCode() is applicable for argument types: (java.lang.String) values: [T04]

有没有办法找到该属性的实际域类?或者对于查找未给出类型的域类的实例(只有具有该类型的属性名称)问题的其他解决方案?

如果我使用类型名称是属性名称大写(“site”->“Site”)的约定来通过 grailsApplication 实例查找类,它会起作用,但我想避免这种情况。

【问题讨论】:

    标签: grails dynamic groovy metaobject


    【解决方案1】:

    Grails 允许您通过 GrailsApplication 实例访问域模型的一些元信息。你可以这样查:

    import org.codehaus.groovy.grails.commons.ApplicationHolder
    import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler
    
    def grailsApplication = ApplicationHolder.application
    def domainDescriptor = grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, "PhysicalSiteAssessment")
    
    def property = domainDescriptor.getPropertyByName("site")
    def type = property.getType()
    assert type instanceof Class
    

    API:

    【讨论】:

    • 谢谢,这行得通。在某处是否有此 API 的一些概述?我一直在寻找类似的东西,但找不到。
    • 除了 javadocs (grails.org/doc/1.1/api/org/codehaus/groovy/grails/commons/…) 之外,我没有见过任何好的参考资料。我还发现查看 Grails 源代码很有帮助。我还在 build-test-data 插件中大量使用这种东西来检查域对象约束,并在您寻找示例时自动生成通过约束的测试对象 (bitbucket.org/tednaleid/grails-test-data/wiki/Home)。
    • 我打电话给getDomainClassgrailsApplication.getDomainClass(PhysicalSiteAssessment).getPropertyByName('site').type
    【解决方案2】:

    【讨论】:

    • 谢谢,它简洁而简短。
    【解决方案3】:

    注意:这个答案不是直接与问题相关,而是与 IMO 相关。

    在尝试解析集合关联的“通用类型”时,我正用头撞墙、地面和周围的树木:

    class A {
        static hasMany = {
            bees: B
        }
    
        List bees
    }
    

    事实证明,最简单但合理的方式只是(我没有尝试,但在 3 小时后):

    A.getHasMany()['bees']
    

    【讨论】:

      【解决方案4】:

      上面由 Siegfried 提供的答案在 Grails 2.4 附近的某个地方已经过时了。 ApplicationHolder 已过时。

      现在,您可以从每个域类所具有的 domainClass 属性中获取真实的类型名称。

      entityClass.domainClass.getProperties().each() {
          println "Property '${it.name}' is of type '${it.type}'"
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-19
        • 2011-01-24
        • 2016-07-09
        相关资源
        最近更新 更多