문제

I trying to build a dynamic query similar to:

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

But it's not working.

If I'm trying this, all is fine:

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

How can I use dynamic domain class name with find?

도움이 되었습니까?

해결책

The simplest way is to use the getDomainClass method:

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

Note that if you're trying to get a single instance by id, use get:

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

and if you want to get multiple instances and you have a list of ids, you can use getAll

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

Also it's a REALLY bad idea to use GStrings with property values embedded - Google 'SQL Injection'

For example to find a person by username:

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

다른 팁

You should be able to do this by explicitly using the GroovyClassLoader:

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

The best way to get a Domain class dynamically is through the GrailsApplication object. Example:

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

You can also use Class.forName() just as you would in Java. Use the 3 parameter version and pass in the current thread context class 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

Classloaders are an ugly topic in Java and JVM frameworks. In Grails, you almost always want to use the thread context classloader. But even better is to use the GrailsApplication interface and avoid the issue altogether.

use GrailsClassUtils

GrailsClassUtils.getShortName(DomainName)

to get the name of the class, so this should work... if I understood the question

def domainClassName = GrailsClassUtils.getShortName(DomainName)
def ids = 1
DomainName.find("from ${domainClassName} as m where m.job = ${ids} ").id
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top