Pregunta

Yo tratando de construir una consulta dinámica similar a:

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

Sin embargo, no está funcionando.

Si estoy tratando de esto, todo está bien:

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

¿Cómo puedo utilizar el nombre de clase de dominio dinámico con find?

¿Fue útil?

Solución

La forma más sencilla es utilizar el método 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

Tenga en cuenta que si usted está tratando de obtener una única instancia por id, get uso:

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

y si usted quiere conseguir varias instancias y usted tiene una lista de ID, puede utilizar getAll

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

También es un realmente mala idea gStrings uso con valores de propiedades incrustadas - Google 'Inyección SQL'

Por ejemplo, para encontrar a una persona por nombre de usuario:

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

Otros consejos

debe ser capaz de hacer esto utilizando explícitamente el GroovyClassLoader:

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

La mejor manera de conseguir una clase de dominio es de forma dinámica a través del objeto GrailsApplication. Ejemplo:

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

También puede utilizar Class.forName() igual que lo haría en Java. Utilice la versión 3 del parámetro y pasar en el cargador de clase de contexto de hilo actual:

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

cargadores de clases son un tema feo en los marcos de Java y JVM. En Grails, casi siempre se desea utilizar el cargador de clases de contexto hilo. Pero aún mejor es utilizar la interfaz GrailsApplication y evitar el problema por completo.

GrailsClassUtils

GrailsClassUtils.getShortName(DomainName)

para obtener el nombre de la clase, por lo que esto debería funcionar ... si he entendido la pregunta

def domainClassName = GrailsClassUtils.getShortName(DomainName)
def ids = 1
DomainName.find("from ${domainClassName} as m where m.job = ${ids} ").id
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top