Как получить тип (класс) свойства объекта домена Grails?
Я пытаюсь динамически создавать объекты домена в Grails и сталкивался с проблемой, что для любого свойства, ссылающегося на другой объект домена, метапроцесс говорит мне, что его тип - это "java.lang.Object", а не ожидаемый тип.
Например:
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)
где свойствоClass извлекается с помощью интроспекции, 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, но я хотел бы избежать этого.
Ответы
Ответ 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:
Ответ 2
Вы можете использовать GrailsClassUtils.getPropertyType(clazz, propertyName)
Ответ 3
Ответ выше, представленный Зигфридом, устарел где-то вокруг Grails 2.4. ApplicationHolder устарел.
Теперь вы можете получить имена реальных типов из свойства domainClass, которое имеет каждый класс домена.
entityClass.domainClass.getProperties().each() {
println "Property '${it.name}' is of type '${it.type}'"
}
Ответ 4
Примечание: этот ответ не связан непосредственно с вопросом, но имеет отношение к ИМО.
Я ударился головой о стену, землю и окружающие деревья, пытаясь разрешить "общий тип" коллекционной ассоциации:
class A {
static hasMany = {
bees: B
}
List bees
}
Оказалось, что самый простой и все же звук был простым (и который я не пробовал, но через 3 часа):
A.getHasMany()['bees']