最近在研究Grails跟db4o的整合。
昨天碰到这么一个奇怪的现象:
下面这段代码中的这句
ObjectSet os = getDb4oTemplate().get(new User(params))
在dev模式下一直报“... cannot be cast to com.db4o.reflect.generic.GenericObject ...”
而在prod模式就正常
class UserService extends Db4oDaoSupport { def objectContainer def login(params) { ObjectSet os = getDb4oTemplate().get(new User(params)) if(os.size() > 0) { println "user found" params.session.user = os.get(0) } else { println "user not found" } } }
而用SODA写query得到的是com.db4o.reflect.generic.GenericObject类的实例
// ObjectSet os = getDb4oTemplate().get(new User(params)) def tpl = getDb4oTemplate() Query q = tpl.query() q.constrain(User.class) q.descend('username').constrain(params.username) q.descend('password').constrain(params.password) ObjectSet os = q.execute()
为什么在dev模式下是GenericObject,而不是我自己的User呢?
我把dev跟prod两种模式下项目目录结构作了对比,有一个显著的区别,就是:前者有个target,下面放着grails/groovy编译得到的classes和其它一些东西;而后者是一标准的J2EE项目的结构,classes都在WEB-INF/classes下,其中就有我的domain class - User。
联想到“The Definitive Guide to Db4o”中的这段话:
虽然它是说Db4o的OM的,但道理应该是一样的。猜想它之所以不能转成User是因为它没看到我的User类。
那我就试着让User出现在它的视野中,试试这句
this.class.classLoader.rootLoader.addURL(new URL("file:///path/to/file"))
貌似无用。
换个方案,把domain classes打成jar包,拷贝到lib下,重启,...,问题解决了,不管是用QBE还是SODA,得到的都是User,而不再是GenericObject了!
但还是有个不方便的地方:每次我修改了domain class,都得重新打包,重新启动,损害了Grails开发的快速特性。
各位路过的朋友有没有完美的解决办法让它实现hot swapping?