Frage

ich versuche, eine dynamische Abfrage ähnlich wie erstellen:

def domain = DomainName
def ids = 1
def domainClass = "$domain" as Class
domainClass.find("from ${domain} as m where m.job = ${ids} ").id

Aber es funktioniert nicht.

Wenn ich dies versuche, alles ist in Ordnung:

def domain = DomainName
def ids = 1
DomainName.find("from ${domain} as m where m.job = ${ids} ").id

Wie kann ich dynamische Domain-Klassennamen finden?

War es hilfreich?

Lösung

Der einfachste Weg ist es, die getDomainClass Methode zu verwenden:

String domainClassName = 'com.foo.bar.Person'
def ids = 1
def domainClass = grailsApplication.getDomainClass(domainClassName).clazz
domainClass.find("from $domainClassName as m where m.job = ${ids} ").id

Beachten Sie, wenn Sie versuchen, eine einzelne Instanz von id, Verwendung get zu bekommen:

long id = 1234
def person = domainClass.get(id)

und wenn Sie mehrere Instanzen erhalten möchten und Sie haben eine Liste von IDs, können Sie getAll verwenden

def ids = [1,2,3,4,5]
def people = domainClass.getAll(ids)

Auch ist es eine wirklich schlechte Idee Verwendung gstrings mit Eigenschaftswerten eingebettet - Google 'SQL Injection'

Zum Beispiel eine Person, die von Benutzernamen zu finden:

String username = 'foo'
def person = domainClass.find(
    "from $domainClassName as m where m.username=:username",
    [username: username])

Andere Tipps

Es soll möglich sein, dies zu tun, indem sie ausdrücklich die GroovyClassLoader mit:

def domain = "DomainName"
def c = new GroovyClassLoader().loadClass(domain)
c.find('...').id

Der beste Weg, um eine Domain-Klasse dynamisch zu bekommen, ist durch das GrailsApplication Objekt. Beispiel:

import org.codehaus.groovy.grails.commons.ApplicationHolder

def domainName = "full.package.DomainName"
def domainGrailsClass = ApplicationHolder.application.getArtefact("Domain", domainName)
def domainClass = domainGrailsClass.getClazz()
domainClass.find("from ${domainGrailsClass.name} as m where m.job = ${ids}").id

Sie können auch Class.forName() verwenden so wie man es in Java. Verwenden Sie die 3 Parameterversion und übergibt im aktuellen Thread-Kontext-Klassenlader:

import grails.util.GrailsNameUtils

def domainName = "full.package.DomainName"
def domainClass = Class.forName(domainName, true, Thread.currentThread().getContextClassLoader())
domainClass.find("from ${GrailsNameUtils.getShortName(domainName)} as m where m.job = ${ids}").id

Classloader sind ein hässliches Thema in Java und JVM-Frameworks. In Grails, Sie wollen fast immer den Thread-Kontext verwenden Classloader. Aber noch besser ist es, die GrailsApplication Schnittstelle zu verwenden und das Problem ganz zu vermeiden.

GrailsClassUtils

GrailsClassUtils.getShortName(DomainName)

den Namen der Klasse erhalten, so sollte diese Arbeit ... wenn ich die Frage

verstanden
def domainClassName = GrailsClassUtils.getShortName(DomainName)
def ids = 1
DomainName.find("from ${domainClassName} as m where m.job = ${ids} ").id
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top