2009-06-10 15 views
14

Intento crear dinámicamente objetos de dominio en Grails y encontré el problema de que para cualquier propiedad que haga referencia a otro objeto de dominio, la metapropiedad me dice que su tipo es "java.lang.Object" y no el tipo esperado.¿Cómo obtengo el tipo (clase) de una propiedad de un objeto de dominio Grails?

Por ejemplo:

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

es el comienzo de una clase de dominio, que hace referencia a otra clase de dominio "Sitio".

Si trato de encontrar dinámicamente los tipos de propiedad para esta clase mediante el uso de este código (en servicio):

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

entonces el resultado es que reconoce las clases de Java, pero no la clase de dominio Grails . La salida contiene las siguientes líneas:

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' 

El problema es que me gustaría utilizar la búsqueda dinámica para encontrar objetos que emparejan, por ejemplo hacer una

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

donde el propertyClass se recupera a través de la introspección, idName es el nombre de la propiedad para mirar hacia arriba (no necesariamente el ID de base de datos) y idValue es el valor de encontrar.

Es todo termina en:

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] 

¿Hay una manera de encontrar la clase de dominio real de la propiedad? ¿O tal vez alguna otra solución al problema de encontrar una instancia de una clase de dominio cuyo tipo no se da (solo un nombre de propiedad que tiene el tipo)?

Funciona si utilizo la convención de que el nombre de tipo es el nombre de la propiedad en mayúscula ("sitio" -> "Sitio") para buscar la clase a través de la instancia de grailsApplication, pero me gustaría evitar eso.

Respuesta

15

Grails le permite acceder a cierta metainformación de su modelo de dominio a través de la instancia de GrailsApplication. Puede mirar hacia arriba de esa manera:

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:

+0

Gracias, eso funciona. ¿Hay alguna descripción general de esta API en alguna parte? Había estado buscando algo como esto pero no pude encontrarlo. –

+0

No hay buenas referencias que haya visto además de los javadocs (http://grails.org/doc/1.1/api/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.html). También encuentro que mirar el código fuente de Grails es muy útil. También utilizo este tipo de cosas en gran medida en el plugin build-test-data para inspeccionar las restricciones de objetos de dominio y generar automáticamente objetos de prueba que superen las restricciones si está buscando ejemplos (http://bitbucket.org/tednaleid/grails- test-data/wiki/Home). –

+1

llamo 'getDomainClass' en su lugar. 'grailsApplication.getDomainClass (PhysicalSiteAssessment) .getPropertyByName ('site'). Type' –

0

Nota: esta respuesta no está directamente relacionada con la pregunta, pero relata suficiente IMO.

estaba golpeando mi cabeza contra la pared, suelo y los árboles circundantes cuando se trata de resolver el "tipo genérico" de una asociación de recogida:

class A { 
    static hasMany = { 
     bees: B 
    } 

    List bees 
} 

apagó la forma más fácil y sin embargo, el sonido era mera (y que no lo intenté, pero después de 3 horas):

A.getHasMany()['bees'] 
2

La respuesta anterior provista por Siegfried se volvió obsoleta en algún lugar alrededor de Grails 2.4. ApplicationHolder está obsoleto.

Ahora puede obtener nombres de tipos reales de la propiedad domainClass que tiene cada clase de dominio.

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