2009-06-10 2 views
14

Я пытаюсь динамически создавать объекты домена в Grails и столкнулся с проблемой, что для любого свойства, ссылающегося на другой объект домена, metaproperty сообщает мне, что его тип - это «java.lang.Object», а не ожидаемый тип.Как получить тип (класс) свойства объекта домена Grails?

Например:

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

начало класса домена, который ссылается на другой домен класса «сайт».

Если я пытаюсь динамически найти типы свойств для этого класса, используя этот код (в службе):

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 этого имени свойства для поиска (не обязательно идентификатор базы данных) и 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] 

Есть ли способ, чтобы найти фактический класс домена для свойства? Или, может быть, какое-то другое решение проблемы поиска экземпляра класса домена, тип которого не указан (только имя свойства, которое имеет тип)?

Это работает, если я использую соглашение о том, что имя типа является именем свойства, заглавным («сайт» -> «Сайт»), чтобы искать класс через экземпляр grailsApplication, но я бы хотел этого избежать.

ответ

15

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:

+0

Спасибо, что работает. Есть ли некоторый обзор этого API где-нибудь? Я искал что-то вроде этого, но не мог его найти. –

+0

Нет никаких хороших ссылок, которые я когда-либо видел помимо javadocs (http://grails.org/doc/1.1/api/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.html). Я также считаю, что поиск исходного кода Grails очень полезен. Я также использую этот материал в плагине build-test-data для проверки ограничений объектов домена и автоматического создания тестовых объектов, которые передают ограничения, если вы ищете примеры (http://bitbucket.org/tednaleid/grails- тест-данных/вики/Home). –

+1

Вместо этого я вызываю 'getDomainClass'. 'grailsApplication.getDomainClass (PhysicalSiteAssessment) .getPropertyByName ('site'). Type' –

0

Примечание: этот ответ не относится непосредственно к вопросу, но относится к числу ИМО.

Я стучал головой к стене, землю и окружающие деревья при попытке решить «общий тип» коллекции ассоциации:

class A { 
    static hasMany = { 
     bees: B 
    } 

    List bees 
} 

Оказалось, самый простой и в то же звук путь был простым (и который я не пробовал, но после 3 часов):

A.getHasMany()['bees'] 
2

Ответ, приведенный Зигфридом, устарел где-то вокруг Grails 2.4. ApplicationHolder устарел.

Теперь вы можете получить настоящие имена типов из domainClass, которые имеют все классы домена.

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