Log4X

链路纵横
[搬家文]Hibernate fetch和lazy-load相关问题 (附json解析小技巧)

hibernate 因为其对象化的原因,因此如果完全不用lazy-load得话,会因为对象之间的互相引用而在查询时候不得不查询大量的不必要数据,若是引用关系较多,数据对象(bo)之间的引用关系就像是一张蜘蛛网,说不定查单一对象就得遍历所有的表。

而为了实现lazy-load,那么查询语句就必须不采用join子句,比如A对象里面有B对象,那么查A对象的时候(比如session.load(A)),只会查询 select A所有字段 from A表,并不会join B,而当需要A对象中的B时,再select B所有字段 from B表 where A-B表关系 。这就是hibernate比较通用的查询方式。

但是当你在A的配置文件中取消B的lazy-load,这种查询方式并没有改变,再load(A)的时候,总是会同时执行以上提到的两句SQL语句,如果A中有N个非延迟加载的关联对象,那么load(A)一次就需要执行N+1句SQL, 这样的效率是非常低的。

简单的方法是在A配置文件中将B相关联的字段 fetch="select"改为 fetch="join" (以前的outer-join 属性已经depricated了,由fetch替代),这样在Load(A)的时候会采用left join B表的方式。不过有一个副作用,criteria.list()得到的不再是一个A元素组成的list,而是一个以Object[2]的数组为元素组成的List,Object[0]放B元素,Object[1]放A元素,不太方便,不知如何设置会正常,需要高手赐教。

这样的另一个坏处就是缺少灵活性了,在需要延迟加载进行优化的时候,就不太方便。

因此最好还是在自己代码中指定.像criteria,query这种对象,都是有fetchmode属性的,这个就是设置连接与否的地方。

如果用HQL,这个问题就很方便了。HQL里面的left join fetch子句,可以非常方便灵活的指定对那些关联对象 join并初始化。像前面这个A 对象,就是: from A a left join fetch a.B ,这样就会将B 用left join 取出。

如果此时A还有一个关联对象C,则这个C对象就会根据A的配置文件中lazy -load 设置,如果延迟加载,则C对象延迟加载,如果不延迟加载,则会附加一条 select C from C表 的SQL语句。

 

:json 就是那种{k1:v1,k2:v2}形式的集合,一般服务器端相应javascript 返回的json结果就是一个字符串如"{k1:v1,k2:v2}" ,而javascript本地方法 eval()可以使其成为 json对象,但是前提是要在这个字符串两端套上小括号。

比如 responseText为ajax返回json结果,则eval(responseText)是错误的,eval("("+responseText+")")才是正确的

posted on 2008-08-13 20:49  YYX  阅读(2290)  评论(0编辑  收藏  举报