您的位置:首页 > 其它

如何解决Hibernate 的N+1问题 .list to map

2014-04-21 01:23 337 查看
【问题】什么时候会遇到N+1的问题?

【备注】 Hibernate默认抓取策略是fetch="select",不是fetch="join",这都是为了延迟加载而准备的。

【出现情况】


1)一对多(one-to-many) ,在1的这方,通过1条sql查找得到了1个对象,由于关联的存在 ,那么又需要将这个对象关联的集合取出,所以合集数量是n还要发出n条sql,于是本来的1条sql查询变成了 1 +n条 。

2)多对一<many-to-one> ,在多的这方,通过1条sql查询得到了n个对象,由于关联的存在,也会将这n个对象对应的1
方的对象取出, 于是本来的1条sql查询变成了1 +n条 。

3)iterator 查询时,一定先去缓存中找(1条sql查集合,只查出ID),在没命中时,会再按ID到库中逐一查找,
产生1+n条SQL。

【解决办法】

1)lazy=true, hibernate3开始已经默认是lazy=true了;lazy=true时不会立刻查询关联对象,只有当需要关联对象(访问其属性,非id字段)时才会发生查询动作。


2)使用二级缓存, 二级缓存的应用将不怕1+N 问题,因为即使第一次查询很慢(未命中),以后查询直接缓存命中也是很快的。刚好又利用了1+N 。

3 ) 当然你也可以设定fetch="join",一次关联表全查出来,但失去了延迟加载的特性。

这些解决方案都不是很好.

好的解决方案是.

利用ENtity的id接口.

interface IdAware{

getId();

}

class EntirtyBean implement IdAware{

long id;

getId(){

return
id

}

}

把List<EntirtyBean>传入到一个Utils.getIds方法中.

自动返回

class Utils{

static List<Long> getIds(List< ? extends IdAware > entirtyBeans){

for( IdAware
bean: entirtyBeans){

list.add(bean.getId());

}

return list;

}

}

使用:

void main(){

List<Long> ids=Utils.getIds(entirtyBeans);

}

如果是两个EntityBean表join新的resutlBean

class ResultBean{

long peopleId;

long tableId;

//类似 compator的接口,利用泛型达到任意Bean的目的

class ResultBeanPeopleId implement IdGenericAware<ResultBean>{

Long getId(ResultBean
object){

return object.peopleID;

}

IdGenericAwareinstance() {

return new ResultBeanTableId ();

}

}

class ResultBeanTableId implement IdGenericAware<ResultBean>{

Long getId(ResultBean object){

return object.tableID;

}

}

IdGenericAwareinstance() {

return newResultBeanTableId ();

}

}

void main(){

List<Long> ids=Utils.getIds(entirtyBeans, ResultBeanTableId.instance() );

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐