فئة Groovy التي تم استدعاؤها ديناميكيا وإيجاد طريقة لا تعمل؟

StackOverflow https://stackoverflow.com/questions/4230181

سؤال

أحاول بناء استعلام ديناميكي مشابه لـ:

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

لكنها لا تعمل.

إذا كنت أحاول هذا ، كل شيء على ما يرام:

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

كيف يمكنني استخدام اسم فئة المجال الديناميكي مع العثور؟

هل كانت مفيدة؟

المحلول

أبسط طريقة هي استخدام 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

لاحظ أنه إذا كنت تحاول الحصول على مثيل واحد عن طريق ID ، فاستخدم get:

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

وإذا كنت ترغب في الحصول على مثيلات متعددة ولديك قائمة بالمعرفات ، يمكنك استخدام Getall

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

كما أنه ملف هل حقا فكرة سيئة لاستخدام GSTRINGS مع قيم الخصائص المضمنة - Google 'SQL Injection'

على سبيل المثال للعثور على شخص بواسطة اسم المستخدم:

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

نصائح أخرى

يجب أن تكون قادرًا على القيام بذلك عن طريق استخدام محمل التحمل الصريح:

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

أفضل طريقة للحصول على فئة المجال ديناميكيًا هي من خلال كائن Grailsapplication. مثال:

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

تستطيع ايضا استخذام Class.forName() تماما كما تفعل في جافا. استخدم إصدار المعلمة 3 ومرر في محمل فئة سياق مؤشر الترابط الحالي:

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

محولات الدرجة هي موضوع قبيح في أطر Java و JVM. في Grails ، أنت ترغب دائمًا في استخدام مرحلة ClassLoader Context Context. ولكن من الأفضل أن تستخدم واجهة Grailsapplication وتجنب المشكلة تمامًا.

استعمال GrailsClassutils

GrailsClassUtils.getShortName(DomainName)

للحصول على اسم الفصل ، لذلك يجب أن يعمل هذا ... إذا فهمت السؤال

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