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 wher开发者_运维百科e 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
精彩评论