GORM的查询方法很方便(可查看http://www.grails.org/doc/1.2.x/ref/Domain%20Classes/findAll.HTML)
但因为我现在用Db4o,根本就不需要ORM,GORM的finders派不上用场。但是GORM把finders以及valIDate注入到Domain Classes中的方式对我们很有启发性。
Db4o提供三种查询方式:QBE, NQ和SODA。其中NQ是type-safe的,在编译期可以作语法检查,在运行期可以被Db4o转化成高效的SODA。我不喜欢在Grails中使用NQ,一是因为这让代码看起来不太漂亮,二是无法保证所有的NQ都会被转化成SODA。
利用Groovy的Closure我写了两个方法:findAll和find,最终执行的都是SODA查询。改一改Grails的FindAllPersistentMethod代码:
package com.grs.db4opersistence.Metaclass;import com.db4o.ObjectContainer;import com.db4o.query.query;import com.grs.utils.GroovyDataUtils;import groovy.lang.MissingMethodException;import groovy.lang.Closure;import org.springframework.beans.SimpleTypeConverter;import java.util.Iterator;import java.util.Map;import java.util.regex.Pattern;/** * The "findAll" persistent static method allows searching for instances * * Usages: * (1) 0 arguments: User.findAll() * (2) 1 argument : User.findAll(sortInfoAndExampleMap) : User.findAll(sort:'dateCreated',order:'asc',department:department) * (3) 1 argument : User.findAll(exampleObject) * (4) 2 arguments: User.findAll(sortInfoMap,exampleObject) : User.findAll([sort:'dateCreated',order:'asc'],userExample) * (5) 1 argument : User.findAll{it.descend('department').constrain(department)} * (6) 2 arguments: User.findAll(sort:'dateCreated',order:'asc'){it.descend('department').constrain(department)} * (7) 2 arguments: User.findAll(sort:'dateCreated',department:department){other complex constraints...} * (8) 3 arguments: User.findAll(sortInfoMap,exampleObject){other complex constraints} * * @author Sam Chen * * Created: Jun 2,2010 * */public class FindAllPersistentMethod extends AbstractStaticPersistentMethod { public static SimpleTypeConverter converter = new SimpleTypeConverter(); public FindAllPersistentMethod(ObjectContainer objectContainer,ClassLoader classLoader) { super(objectContainer,classLoader,Pattern.compile("^findAll$")); } protected Object doInvokeInternal(final Class clazz,String methodname,Closure additionalCriteria,final Object[] arguments) { return doFindAll(clazz,methodname,additionalCriteria,arguments); } protected final Object doFindAll(final Class clazz,final Object[] arguments) { if (arguments.length == 0) { query q = getDb4oTemplate().query(); q.constrain(clazz); q.descend("deleted").constrain(false); return q.execute(); } if (arguments.length == 1) { Object arg = arguments[0]; if(clazz.isAssignableFrom(arg.getClass())) { return getDb4oTemplate().queryByExample(arg); } else if(arg instanceof Map) { query q = getDb4oTemplate().query(); q.constrain(clazz);q.descend("deleted").constrain(false); Map map = (Map) arg; if (map.containsKey("sort") && map.containsKey("order")) { if (map.get("order").equals("desc")) { q.descend((String)map.get("sort")).orderDescending(); } else { q.descend((String)map.get("sort")).orderAscending(); } } for(Iterator<String> it = map.keySet().iterator(); it.hasNext();) { String key = it.next(); if("sort".equals(key) || "order".equals(key)) { continue; } q.descend(key).constrain(map.get(key)); } return q.execute(); } else if(arg instanceof Closure) { query q = getDb4oTemplate().query(); q.constrain(clazz);q.descend("deleted").constrain(false); ((Closure)arg).call(q); return q.execute(); } else { throw new MissingMethodException(methodname,clazz,arguments); } } if (arguments.length == 2) { Object arg0 = arguments[0]; Object arg1 = arguments[1]; if(!(arg0 instanceof Map)) { throw new MissingMethodException(methodname,arguments); } query q = getDb4oTemplate().query(); q.constrain(clazz);q.descend("deleted").constrain(false); Map map = (Map) arg0; if (map.containsKey("sort") && map.containsKey("order")) { if (map.get("order").equals("desc")) { q.descend((String)map.get("sort")).orderDescending(); } else { q.descend((String)map.get("sort")).orderAscending(); } } for (Iterator<String> it = map.keySet().iterator(); it.hasNext();) { String key = it.next(); if("sort".equals(key) || "order".equals(key)) { continue; } q.descend(key).constrain(map.get(key)); } if (arg1 instanceof Closure) { ((Closure) arg1).call(q); } else if (arg1 instanceof Map || clazz.isAssignableFrom(arg1.getClass())) { // extract propertIEs from the domain object... applyConstraintsFromExample(arg1,q); } else { throw new MissingMethodException(methodname,arguments); } return q.execute(); } if (arguments.length == 3) { Object arg0 = arguments[0]; // sortInfoMap Object arg1 = arguments[1]; // example Object arg2 = arguments[2]; // closure if(!(arg0 instanceof Map) || !(arg1 instanceof Map || clazz.isAssignableFrom(arg1.getClass())) || !(arg2 instanceof Closure)) { throw new MissingMethodException(methodname,arguments); } query q = getDb4oTemplate().query(); q.constrain(clazz);q.descend("deleted").constrain(false); Map map = (Map) arg0; if (map.containsKey("sort") && map.containsKey("order")) { if (map.get("order").equals("desc")) { q.descend((String)map.get("sort")).orderDescending(); } else { q.descend((String)map.get("sort")).orderAscending(); } } // extract propertIEs from the domain object... applyConstraintsFromExample(arg1,q); ((Closure)arg2).call(q); return q.execute(); } throw new MissingMethodException(methodname,arguments); } private voID applyConstraintsFromExample(Object o,query q) { Map propertIEs = (o instanceof Map ? (Map)o : GroovyDataUtils.getPropertIEs(o)); for(Iterator<String> it = propertIEs.keySet().iterator(); it.hasNext();) { String key = it.next(); Object v = propertIEs.get(key); if(v != null) { q.descend(key).constrain(v); } } }}
有了FindAllPersistentMethod方法,FindPersistentMethod就很简单了:
package com.grs.db4opersistence.Metaclass;import com.db4o.ObjectContainer;import com.db4o.ObjectSet;import groovy.lang.Closure;import org.springframework.beans.SimpleTypeConverter;import java.util.regex.Pattern;/** * <p> * The "find" persistent static method allows searching for an instance * * @author Sam Chen * Created: Jun 2,2010 * */public class FindPersistentMethod extends FindAllPersistentMethod { public static SimpleTypeConverter converter = new SimpleTypeConverter(); public FindPersistentMethod(ObjectContainer objectContainer,classLoader); this.setPattern(Pattern.compile("^find$")); } protected Object doInvokeInternal(final Class clazz,final Object[] arguments) { ObjectSet os = (ObjectSet)this.doFindAll(clazz,arguments); return os.size() > 0 ? os.get(0) : null; }}
,同时修改它的method signature:
def findAllMethod = new FindAllPersistentMethod(objectContainer,application.classLoader)/** * Usages: * (1) 0 arguments: User.findAll() * (2) 1 argument : User.findAll(sortInfoAndExampleMap) : User.findAll(sort:'dateCreated',exampleObject){other complex constraints} */mc.static.findAll = {-> findAllMethod.invoke(mc.javaClass,"findAll",[] as Object[])}mc.static.findAll = {Object sortMapOrExampleOrClosure-> findAllMethod.invoke(mc.javaClass,[sortMapOrExampleOrClosure] as Object[])}mc.static.findAll = {Map map,Object eoc -> findAllMethod.invoke(mc.javaClass,[map,eoc] as Object[])}mc.static.findAll = {Map map,Object example,Closure c-> findAllMethod.invoke(mc.javaClass,example,c] as Object[])}
再写一点测试代码:
package com.grs.sctmsimport grails.test.*class FindMethodIntegrationTests extends GrailsUnitTestCase { protected voID setUp() { super.setUp() for (int i = 0; i < 100; i++) { new User(username:"user#$i",password:"pwd").save() } new User(username:"sam.ds.chen@xxx.com",password:"sam's password").save() } protected voID tearDown() { super.tearDown() } voID testFindAllWithEmptyArgument() { def users = User.findAll() assertEquals 101,users.size() } voID testFindAllWithOneArguments() {// def users = User.findAll(sort:'username',order:'asc')// assertEquals 'sam.ds.chen@xxx.com',users[0].username def users = User.findAll(sort:'username',password:'pwd') assertEquals 100,users.size() users = User.findAll(new User(password:'pwd')) assertEquals 100,users.size() users = User.findAll{it.descend('password').constrain('pwd')} assertEquals 100,users.size() } voID testFindAllWithTwoArguments() { def users = User.findAll([sort:'username',new User(password:'pwd')) assertEquals 100,users.size() users = User.findAll(sort:'username',order:'asc') { it.descend('username').constrain('user#').like() } assertEquals 100,password:"sam's password") { it.descend('username').constrain('sam.ds.chen@xxx.com') } assertEquals 1,users.size() assertEquals "sam.ds.chen@xxx.com",users[0].username } voID testFindAllWithThreeArguments() { def users = User.findAll([sort:'username',[password:"sam's password"]) { } assertEquals 1,users[0].username users = User.findAll([sort:'username',new User(password:"sam's password")) { it.descend('password').constrain("sam's password") } assertEquals 1,users[0].username }}
测试结果
-------------------------------------------------------Running 2 integration tests...Running test com.grs.sctms.FindMethodIntegrationTests...PASSEDRunning test com.grs.sctms.ValIDationIntegrationTests...PASSEDTests Completed in 2485ms ...-------------------------------------------------------Tests passed: 5Tests Failed: 0-------------------------------------------------------
不过有个小问题: 测试代码中被注释掉的部分
// def users = User.findAll(sort:'username',users[0].username
通不过。每次跑的
users[0].username
的值都不一样 - 看来测试环境下排序没生效。而用grails run-app把它跑起来的时候,经deBUG证实数据是排好序的!怀疑是Grails的BUG...
总结以上是内存溢出为你收集整理的Grails hack之改写findAll和find方法全部内容,希望文章能够帮你解决Grails hack之改写findAll和find方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)