什么是hibernate N+1查询
在Session的缓存中存放的是相互关联的对象图。默认情况下,当Hibernate从数据库中加载Customer对象时,会同时加载所有关联的Order对象。以Customer和Order类为例,假定ORDERS表的CUSTOMER_ID外键允许为null,图1列出了CUSTOMERS表和ORDERS表中的记录。
以下Session的find()方法用于到数据库中检索所有的Customer对象:
List customerLists=session.find("from Customer as c");
运行以上find()方法时,Hibernate将先查询CUSTOMERS表中所有的记录,然后根据每条记录的ID,到ORDERS表中查询有参照关系的记录,Hibernate将依次执行以下select语句:
select * from CUSTOMERS;
select * from ORDERS where CUSTOMER_ID=1;
select * from ORDERS where CUSTOMER_ID=2;
select * from ORDERS where CUSTOMER_ID=3;
select * from ORDERS where CUSTOMER_ID=4;
通过以上5条select语句,Hibernate最后加载了4个Customer对象和5个Order对象,在内存中形成了一幅关联的对象图,参见图2。
Hibernate在检索与Customer关联的Order对象时,使用了默认的立即检索策略。这种检索策略存在两大不足:
(1) select语句的数目太多,需要频繁的访问数据库,会影响检索性能。如果需要查询n个Customer对象,那么必须执行n+1次select查询语句。这就是经典的n+1次select查询问题。 这种检索策略没有利用SQL的连接查询功能,例如以上5条select语句完全可以通过以下1条select语句来完成:
select * from CUSTOMERS left outer join ORDERS
on CUSTOMERS.ID=ORDERS.CUSTOMER_ID
以上select语句使用了SQL的左外连接查询功能,能够在一条select语句中查询出CUSTOMERS表的所有记录,以及匹配的ORDERS表的记录。
(2)在应用逻辑只需要访问Customer对象,而不需要访问Order对象的场合,加载Order对象完全是多余的操作,这些多余的Order对象白白浪费了许多内存空间。
为了解决以上问题,Hibernate提供了其他两种检索策略:延迟检索策略和迫切左外连接检索策略。延迟检索策略能避免多余加载应用程序不需要访问的关联对象,迫切左外连接检索策略则充分利用了SQL的外连接查询功能,能够减少select语句的数目。
附一篇 hibernate的解决n+1的方法
Hibernate的检索策略包括类级别检索策略和关联级别检索策略。
类级别检索策略有立即检索和延迟检索,默认的检索策略是立即检索。在Hibernate映射文件中,通过在<class>上配置 lazy属性来确定检索策略。对于Session的检索方式,类级别检索策略仅适用于load方法;也就说,对于get、qurey检索,持久化对象都会被立即加载而不管lazy是false还是true.一般来说,我们检索对象就是要访问它,因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常(立即检索的情况下),因此我个人并不建议使用load检索;而由于<class>中的lazy属性还影响到多对一及一对一的检索策略,因此使用load方法就更没必要了。
关联级别检索策略有立即检索、延迟检索和迫切左外连接检索。对于关联级别检索,又可分为一对多和多对多、多对一和一对一两种情况讨论。
1)立即检索:这是一对多默认的检索策略,此时lazy=false,outer-join=false.尽管这是默认的检索策略,但如果关联的集合是无用的,那么就不要使用这种检索方式。
2)延迟检索:此时lazy=true,outer-join=false(outer-join=true是无意义的),这是优先考虑的检索方式。
3)迫切左外连接检索:此时 lazy=false,outer-join=true,这种检索策略只适用于依靠id检索方式(load、get),而不适用于query的集合检索(它会采用立即检索策略)。相比于立即检索,这种检索策略减少了一条sql语句,但在Hibernate中,只能有一个<set>配置成 outer-join=true.
多对一和一对一检索策略一般使用<many-to-one>、<one-to-one>配置。<many- to-one>中需要配置的属性是 outer-join,同时还需要配置one端关联的<class>的lazy属性(配置的可不是<many-to-one>中的lazy哦),它们的组合后的检索策略如下:
1) outer-join=auto:这是默认值,如果lazy=true为延迟检索,如果lazy=false为迫切左外连接检索
2) outer-join=true,无关于lazy,都为迫切左外连接检索。
3) outer-join=false,如果lazy=true为延迟检索,否则为立即检索。
可以看到,在默认的情况下(outer-join=auto,lazy=false),对关联的one端对象Hibernate采用的迫切左外连接检索。依我看,很多情况下,我们并不需要加载one端关联的对象(很可能我们需要的仅仅是关联对象的id);另外,如果关联对象也采用了迫切左外连接检索,就会出现select语句中有多个外连接表,如果个数多的话会影响检索性能,这也是为什么Hibernate通过 hibernate.max_fetch_depth属性来控制外连接的深度。对于迫切左外连接检索,query的集合检索并不适用,它会采用立即检索策略。
对于检索策略,需要根据实际情况进行选择。对于立即检索和延迟检索,它们的优点在于select语句简单(每张表一条语句)、查询速度快,缺点在于关联表时需要多条select语句,增加了访问数据库的频率。因此在选择即检索和延迟检索时,可以考虑使用批量检索策略来减少select语句的数量(配置batch-size属性)。对于切左外连接检索,优点在于select较少,但缺点是select语句的复杂度提高,多表之间的关联会是很耗时的操作。另外,配置文件是死的,但程序是活的,可以根据需要在程序里显示的指定检索策略(可能经常需要在程序中显示指定迫切左外连接检索)。为了清楚检索策略的配置效果如何,可以配置show_sql属性查看程序运行时Hibernate执行的sql语句。
什么是hibernate N+1查询相关推荐
- Hibernate(九)HQL查询
一.Hibernate提供的查询方式 OID查询方式:主键查询.通过get()或者load()方法加载指定OID的对象查询结果为一个 HQL查询方式:通过Query接口使用HQL语言进行查询 QBC查 ...
- Hibernate:SQL查询 addScalar()或addEntity()
Hibernate除了支持HQL查询外,还支持原生SQL查询. 对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取这个接口.该 ...
- hibernate mysql 模糊查询_服务器-hibernate操作mysql,模糊查询时中文查不到,数字和英文可以查到...
用hibernate做模糊查询,页面传递参数也处理了乱码 @Action(value="searchNameByad") public String searchNameByad( ...
- Hibernate 笔记 HQL查询
http://www.cnblogs.com/zilong882008/archive/2011/11/05/2237123.html Hibernate 笔记 HQL查询(一)单属性,多属性查询 H ...
- (2)hibernate HQL命名查询和Query接口的分页查询
一 hql命名查询 hibernate中对动态查询参数绑定提供了丰富的支持,那么什么是查询参数动态绑定呢?其实如果我们熟悉传统JDBC编程的话,我们就不难理解查询参数动态绑定,如下代码传统JDBC的 ...
- Hibernate Query数据查询
2019独角兽企业重金招聘Python工程师标准>>> 主要由三种查询:HQL查询.Criteria条件查询.SQL查询. 以下分别讲解 1. HQL查询 HQL(Hibernate ...
- Hibernate Native SQL查询示例
Hibernate Native SQL查询示例 欢迎使用Hibernate Native SQL Query示例教程.我们在前面的文章中研究了Hibernate查询语言和Hibernate Crit ...
- java hql多条件查询_JSP 开发之hibernate的hql查询多对多查询
JSP 开发之hibernate的hql查询多对多查询 在hibernate的hql查询中,假如说分组信息与试题是多对多关系,那么我们要在hql查询中对含有多个分组信息的试题都要查询出来.并同时查询出 ...
- hibernate hql 关联查询_Hibernate【关联查询篇】
1. Hibernate 关联查询 1.1. 说明 Hibernate框架支持通过配置映射关系实现多表关联查询. 1.2. 类型 关联查询分为:一对一(one-to-one).一对多(one-to-m ...
最新文章
- python判断括号有效,在Python中检查括号是否平衡
- RFID助力汽车零部件厂商识别冲压工具位置
- JZOJ 3871. 【NOIP2014八校联考第4场第1试10.19】无聊的游戏(game)
- 同一个硬盘装多个linux系统,在一个硬盘上安装两个Linux操作系统方法
- mysql数据库与oracle_oracle与mysql数据库的区别
- NIO和BIO如何影响应用程序的设计
- Hive _分桶及抽样查询
- 使用 Chrome 开发者工具的 lighthouse 功能分析 web 应用的性能问题
- Python机器学习:KNN算法02scikit-learn中的机器学习算法封装
- vim“用sudo写”技巧如何工作?
- 如何选择适合自己的相机?
- 服务器系统开机提示0xc000007b,0xc000007b蓝屏解决方法
- 大白话讲解,大数据基本术语
- Git:gnutls_handshake() failed: A TLS packet with unexpected length was received
- Origin画图笔记
- 微信小程序修改制作生成头像——校庆头像制作小程序
- 超全的学习资料——Oracle 从入门到精通
- Navicat Premium安装和激活
- c语言cast的用法,static_cast 用法
- 子类不能抛出新的异常
热门文章
- MySQL 基本信息的查询(初始化配置信息 my.ini)
- 命名之法 —— 书名及角色、武功(金庸)
- 【智力题】拿硬币(数数字)、游戏
- html经历了几个版本,HTML 的上一个版本诞生于 1999 年. 自从那以后, Web 世界已经经历了巨变....
- 华为笔记本支持鸿蒙,华为 EMUI11 多屏协同说明新增支持鸿蒙 2.0 手机连接
- linux创建空镜像,Docker创建base镜像
- 螺杆泵matlab,基于Matlab与VC++混合编程的螺杆泵转子型线设计
- 自学python能找到工作吗-自学 Python,我是如何找到工作的?
- python数据分析-为什么Python对大数据分析那么很重要?
- 用python画玫瑰花-用python画一朵玫瑰花