文档章节

hibernate N+1问题

毅屺
 毅屺
发布于 2016/03/20 22:38
字数 838
阅读 83
收藏 3

Hibernate N+1 问题及解决办法

问题出现的原因:

Hibernate 中常会用到 set , bag 等集合表示 1 对多的关系,在获取实体的时候就能根据关系将关联的对象或者对象集取出,还可以设定 cacade 进行关联更新和删除。这不得不说 hibernate 的 orm 做得很好,很贴近 oo的使用习惯了。

但是对数据库访问还是必须考虑性能问题的,在设定了 1 对多这种关系之后, 查询就会出现传说中的 n+1 问题。

一对多: 在一方,查找得到了 n 个对象,那么又需要将 n 个对象关联的集合取出,于是本来的一条 sql 查询变成了 n+1 条;

多对一: 在多方,查询得到了 m 个对象,那么也会将 m 个对象对应的 1 方的对象取出, 也变成了 m+1 ;

解决问题的方法:

      1、 使用 fetch 抓取, Hibernate 抓取策略分为单端代理和集合代理的抓取策略。

Hibernate 抓取策略 ( 单端代理的抓取策略 ) 

   保持默认也就是如下 :

    <many-to-one name="clazz" cascade="save-update" fetch="select" />

    fetch="select" 就是另外发送一条 select 语句抓取当前对象关联实体或者集合设置 fetch="join"

     <many-to-one name="clazz" cascade="save-update" fetch="join"/>

Hibernate 会通过 select 语句使用外连接来加载器关联实体活集合此时 lazy 会失效

       Hibernate 抓取策略 ( 集合代理的抓取策略 ) 

            保持默认( fetch="select" )也就是如下 :

        <set name="students" inverse="true">

                 <key column="clazz"/>

                 <one-to-many class="com.june.hibernate.Student"/>

             </set>

             1)fetch="select" 会另外发出一条语句查询集合

             2) 设置 fetch="join" 采用外连接集合的 lazy 失效

             3) 这只 fetch="subselect" 另外发出一条 select 语句抓取前面查询到的所有的实体对象的关联集合 fetch只对 HQL 查询产生影响其他的则不会

       2、 使用 map 直接搜索需要的列

如:产品 product 和产品分类 product_category 两张表,多对一关系。查询产品列表时

select new Map(p.id as id, p.name as name, p.category.name as categoryName) from Product p

对数据库访问还是必须考虑性能问题的, 在设定了1 对多这种关系之后, 查询就会出现传说中的n +1 问题。 
1 )1 对多,在1 方,查找得到了n 个对象, 那么又需要将n 个对象关联的集合取出,于是本来的一条sql查询变成了n +1 条 
2)多对1 ,在多方,查询得到了m个对象,那么也会将m个对象对应的1 方的对象取出, 也变成了m+1

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

2)二级缓存, 在对象更新,删除,添加相对于查询要少得多时, 二级缓存的应用将不怕n +1 问题,因为即使第一次查询很慢,之后直接缓存命中也是很快的。 
不同解决方法,不同的思路,第二条却刚好又利用了n +1 。

3) 当然你也可以设定fetch=join(annotation : @ManyToOne() @Fetch(FetchMode.JOIN))

 

© 著作权归作者所有

共有 人打赏支持
上一篇: date 输出格式
下一篇: spring MVC文件上传
毅屺
粉丝 7
博文 35
码字总数 23276
作品 0
海淀
程序员
私信 提问
有没有必要去刻意避免n+1查询

现在各种orm框架盛行,感觉orm非常方便,也非常强大,也符合面向对象的编程思想.不过带来一个问题,就是n+1查询的问题.面试的时候好多公司都是问怎么样去避免n+1查询.n+1查询真的有必要去避免吗?...

无痕的旋律
2013/07/10
1K
9
不考虑缓存,对象关联用join还是in?

例如帖子列表,要返回帖子-发帖人的列表。我看到像bbs这种都是使用缓存,然后根据id查询,此情况下是利用n+1提高性能。 但是如果不使用缓存,是用join还是先取出帖子列表,然后遍历后取出用户...

铂金小虫
2014/08/10
320
7
Spring Data JPA一对多假分页问题

Sping Data JPA + hibernate 我遇到一个问题,在调用JpaSpecificationExecutor.findAll(Specification spec, Pageable pageable)方法时,当被查询的这个entity有一对多的关联关系时,为了防止...

程序员甲
2017/05/27
157
0
Hibernate查询缓存全面分析

这里介绍Hibernate查询缓存对Iterator不起作用,只对List起作用。下面我们这种介绍把二级缓存 和 Hibernate查询缓存 结合使用。 AD: 本文向大家介绍Hibernate查询缓存,可能好多人还不了解H...

dong.li
2012/04/24
0
0
Hibernate(五)——面向对象查询语言和锁

Hibernate做了数据库中表和我们实体类的映射,使我们不必再编写sql语言了。但是有时候查询的特殊性,还是需要我们手动来写查询语句呢,Hibernate框架为了解决这个问题给我们提供了HQL(Hiber...

凡尘里的一根葱
2015/11/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

当S8遇上边缘计算:谈阿里云ENS对直播业务场景的支撑

摘要: 类似S8赛事这样的大型活动直播的特点和技术挑战是什么?为什么业务要下沉到边缘?自建边缘节点和与云服务厂商合作到底该如何选择?边缘节点服务(ENS)又是如何进行技术支撑?提供的针...

阿里云官方博客
6分钟前
1
0
supervisor安装配置

supervisor安装配置 安装 wget -c https://files.pythonhosted.org/packages/44/60/698e54b4a4a9b956b2d709b4b7b676119c833d811d53ee2500f1b5e96dc3/supervisor-3.3.4.tar.gztar -zxvf su......

jackmanwu
17分钟前
1
0
laravel定时器

民间高手: https://blog.csdn.net/zhezhebie/article/details/79205414 官方文档: https://laravel-china.org/docs/laravel/5.5/scheduling/1325...

vio小黑
39分钟前
0
0
Apache Zeppelin安装及使用

Apache Zeppelin官网:http://zeppelin.apache.org/ Apache Zeppelin介绍:A web-based notebook that enables interactive data analytics. You can make beautiful data-driven, interacti......

GordonNemo
41分钟前
4
0
关于python开发多个项目环境配置Anaconda

关于Anaconda用来管理Python的包和环境 下载并安装Anaconda 创建项目:windows键+R ==> 进入CMD => 输入conda create -n 项目名称 python=3 conda info -e 查看项目以及项目所在的位置,默认...

上官清偌
42分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部