Domanda

I cercando di costruire una query dinamica simile a:

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

Ma non funziona.

Se io sto cercando questo, tutto va bene:

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

Come posso utilizzare dinamica nome della classe di dominio con find?

È stato utile?

Soluzione

Il modo più semplice è quello di utilizzare il metodo getDomainClass:

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

Si noti che se si sta cercando di ottenere una singola istanza da id, uso get:

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

e se si vuole ottenere di più istanze e si dispone di un elenco di ID, è possibile utilizzare getAll

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

Inoltre è un VERAMENTE cattiva idea di utilizzare gstrings con proprietà dai valori incorporati - Google 'SQL Injection'

Per esempio, per trovare una persona con nome utente:

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

Altri suggerimenti

Si dovrebbe essere in grado di fare questo in modo esplicito utilizzando il GroovyClassLoader:

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

Il modo migliore per ottenere una classe di dominio dinamico è attraverso l'oggetto GrailsApplication. Esempio:

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

È inoltre possibile utilizzare Class.forName() proprio come si farebbe in Java. Utilizzare la versione 3 parametro e passare la corrente classe contesto di thread loader:

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 sono un brutto argomento nel framework Java e JVM. In Grails, si vuole quasi sempre di utilizzare il programma di caricamento classe contesto thread. Ma ancora meglio è quello di utilizzare l'interfaccia GrailsApplication ed evitare il problema del tutto.

GrailsClassUtils

GrailsClassUtils.getShortName(DomainName)

per ottenere il nome della classe, quindi questo dovrebbe funzionare ... se ho capito la domanda

def domainClassName = GrailsClassUtils.getShortName(DomainName)
def ids = 1
DomainName.find("from ${domainClassName} as m where m.job = ${ids} ").id
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top