2009-06-10 13 views
14

Próbuję dynamicznie tworzyć obiekty domen w Grails i napotkałem problem, że dla każdej właściwości odwołującej się do innego obiektu domeny metaproperty mówi mi, że jego typ to "java.lang.Object", a nie oczekiwany typ.Jak uzyskać typ (klasę) właściwości obiektu domeny Grails?

Na przykład:

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

jest początkiem klasy domeny, która odwołuje się do innej klasy domeny "site".

Gdy próbuję dynamicznie znaleźć rodzaje nieruchomości do tej klasy przy użyciu tego kodu (w serwisie):

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

wtedy wynikiem jest to, że rozpoznaje klas Javy, ale nie klasy domeny Grails . Dane wyjściowe zawierają następujące linie:

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' 

Problem polega na tym, że chciałbym użyć wyszukiwania dynamicznego do znalezienia pasujących obiektów, np. zrobić

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

gdzie propertyClass jest pobierane poprzez introspekcję, idName to nazwa obiektu patrzeć (niekoniecznie identyfikator bazy danych) i idValue jest wartością znaleźć.

To wszystko kończy się:

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] 

Czy istnieje sposób, aby znaleźć rzeczywiste klasy domeny dla nieruchomości? A może jakieś inne rozwiązanie problemu znalezienia instancji klasy domeny, której typ nie jest podany (tylko nazwa właściwości, która ma typ)?

Działa, jeśli używam konwencji, której nazwa typu jest nazwą dużej litery ("site" -> "Site"), aby wyszukać klasę za pośrednictwem instancji grailsApplication, ale chciałbym tego uniknąć.

Odpowiedz

15

Grails umożliwia dostęp do niektórych meta-informacji modelu domeny za pośrednictwem instancji GrailsApplication. Można to sprawdzić w ten sposób:

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

Dzięki, że działa. Czy jest gdzieś jakiś przegląd tego API? Szukałem czegoś takiego, ale nie mogłem go znaleźć. –

+0

Nie ma żadnych dobrych referencji, które kiedykolwiek widziałem poza javadocs (http://grails.org/doc/1.1/api/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.html). Zauważyłem też, że bardzo pomocne jest przeglądanie kodu źródłowego Grails. Używam również tego rodzaju rzeczy w wtyczce build-test-data do sprawdzania ograniczeń obiektów domeny i automatycznie generuję obiekty testowe, które przechodzą ograniczenia, jeśli szukasz przykładów (http://bitbucket.org/tednaleid/grails- test-data/wiki/Home). –

+1

Zamiast tego nazywam 'getDomainClass'. 'grailsApplication.getDomainClass (PhysicalSiteAssessment) .getPropertyByName (" site "). Type" –

0

Uwaga: ta odpowiedź nie jest bezpośrednio związana z pytaniem, ale dotyczy odpowiednio IMO.

byłem walić głową do ściany, ziemię i okolicznych drzew, próbując rozwiązać „typ rodzajowy” z stowarzyszenia Kolekcja:

class A { 
    static hasMany = { 
     bees: B 
    } 

    List bees 
} 

Okazało się najprostszym i jeszcze dźwięk droga była sama (a które nie próbowałem, ale po 3 godzinach):

A.getHasMany()['bees'] 
2

Powyższa odpowiedź dostarczona przez Siegfried stała się przestarzała gdzieś w okolicach Grails 2.4. ApplicationHolder jest przestarzały.

Teraz można uzyskać prawdziwe nazwy typów z właściwości domainClass, która ma każda klasa domeny.

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