如何解决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() );
}
【备注】 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() );
}
相关文章推荐
- 解决Win32 SDK编程添加list control控件程序无法运行的问题 . 和如何画进度条
- 解决hibernate @OneToOne 无限循环引用问题
- git使用中遇到的remote:Permission to xxx denied to xxx问题如何解决
- Spark 2.0 DataFrame map操作中Unable to find encoder for type stored in a Dataset问题的分析与解决
- jquery checkBox undefined 和hibernate 联合主键的注意事项 集合转数组 数组转集合 map list 数组 判空 问题
- 解决Failed to instantiate [java.util.List]: Specified class is an interface问题
- Hibernate 解决n+1问题
- 如何建立第一个hibernate项目以及解决相关出现的问题
- 如何解决"unable to get project file from web server"问题
- 如何解决 hibernate 多级对象加载并避免join和N+1次查询问题
- apache问题you don't have permission to access / on this server如何解决
- Java解决No enclosing instance of type PrintListFromTailToHead is accessible问题
- linux中ssh登录Permanently added (RSA) to the list of known hosts问题解决
- 如何解决List集合类数据源变更UI不能自动刷新的问题
- linq to sql 中,如何解决多条件查询问题,答案,用表达式树! (下)
- Hibernate注解中的manytomany级联与不级联删除问题的解决
- 解决No Hibernate Session bound to thread, and configuration does not allow create tansactional的问题
- 安装新android studio时候碰到问题 unable to access Android SDK add-on list,解决
- 解决ssh不能添加已访问的主机到信任列表的问题(Failed to add the host to the list of known hosts)
- Unity2017 Unable to list target platforms.Please make sure the android sdk path is correct.问题解决!