Question

J'essaie de construire une requête dynamique similaire à:

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

Mais il ne fonctionne pas.

Si j'essaie cela, tout ira bien:

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

Comment puis-je utiliser le nom de classe de domaine dynamique trouver?

Était-ce utile?

La solution

La façon la plus simple est d'utiliser la méthode 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

Notez que si vous essayez d'obtenir une seule instance par id, utilisez get:

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

et si vous voulez obtenir plusieurs instances et vous avez une liste des ids, vous pouvez utiliser getAll

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

En outre, il est un vraiment mauvaise idée d'utiliser Gstrings avec des valeurs de propriété intégrées - Google 'Injection SQL'

Par exemple, pour trouver une personne par nom d'utilisateur:

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

Autres conseils

Vous devriez être en mesure de le faire en utilisant explicitement le GroovyClassLoader:

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

La meilleure façon d'obtenir une classe de domaine est dynamique à travers l'objet GrailsApplication. Exemple:

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

Vous pouvez également utiliser Class.forName() comme vous le feriez en Java. Utilisez la version 3 paramètres et passer dans la classe du contexte du fil chargeur:

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

classloaders sont un sujet laid dans les cadres Java et JVM. Dans Grails, vous voulez presque toujours utiliser le contexte de fil classloader. Mais encore mieux est d'utiliser l'interface GrailsApplication et d'éviter la question tout à fait.

GrailsClassUtils

GrailsClassUtils.getShortName(DomainName)

pour obtenir le nom de la classe, ce qui devrait travailler ... si je comprends bien la question

def domainClassName = GrailsClassUtils.getShortName(DomainName)
def ids = 1
DomainName.find("from ${domainClassName} as m where m.job = ${ids} ").id
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top