在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语句的数目。

转载于:https://www.cnblogs.com/sunwei2012/archive/2010/01/03/1638421.html

什么叫n+1次select查询问题?相关推荐

  1. 如何让SELECT 查询结果额外增加自动递增序号

      图表1   如果数据表本身并不内含自动地增编号的字段时,要怎么做才能够让SELECT查询结果如图表1所示,额外增加自动递增序号呢?我们提供下列五种方法供您参考:   USE北风贸易; GO /* ...

  2. mysql之select查询

    SELECT查询数据 单表查询 语法 SELECT 字段1,字段2... FROM 表名WHERE 条件GROUP BY fieldHAVING 筛选ORDER BY fieldLIMIT 限制条数 ...

  3. mysql select表达式_MySQL数据库SELECT查询表达式解析

    数据的管理在很大一部分是在进行查找工作,而SELECT占据了很大的一部分 SELECT select_expr [,select_expr...] [ FROM table_reference WHE ...

  4. 关于SubSonic3.0插件使用SqlQuery或Select查询时产生的System.NullReferenceException异常修复...

    早上在编写执行用例时,突然爆异常System.NullReferenceException: 未将对象引用设置到对象的实例 执行代码: 未将对象引用设置到对象的实例. 说明: 执行当前 Web 请求期 ...

  5. 在Oracle中如何让SELECT查询绕过UNDO

    是否有想过如何在Oracle中实现脏读(dirty read),在Oracle官方文档或者Asktom的时候显然会提到Oracle是不实现脏读的, 总是有undo来提供数据块的前镜像(before i ...

  6. MySQL之SELECT查询表达式

    数据的管理在很大一部分是在进行查找工作,而SELECT占据了很大的一部分 SELECT select_expr [,select_expr...] [FROM table_referenceWHERE ...

  7. 为什么忘记commit也会造成select查询的性能问题

    今天遇到一个很有意思的问题,一个开发人员反馈在测试服务器ORACLE数据库执行的一条简单SQL语句非常缓慢,他写的一个SQL没有返回任何数据,但是耗费了几分钟的时间.让我检查分析一下原因,分析解决过后 ...

  8. sqlite3 select查询一列_Python成为专业人士笔记–Sqlite3 模块

    "专业人士笔记"系列目录: 创帆云:Python成为专业人士笔记--强烈建议收藏!每日持续更新!​zhuanlan.zhihu.com Sqlite3 -一个不需要独立服务器进程的 ...

  9. php调用mysql查询结果_php - 在php脚本中处理select查询结果集

    在php脚本中执行select查询命令,也是调用mysql_query()函数,但是和执行DML不同的是,执行SELECT 命令后,mysql_query()函数的返回值是一个资源的引用指针(结果集) ...

最新文章

  1. 一个button导致的慘案
  2. java切割文件_Java如何将大文件切割成小文件
  3. VMware中的桥接模式、NAT(网络地址转换模式)、Host-only(主机模式):转自:http://blog.chinaunix.net/uid-11798538-id-3061551.html
  4. php教程链接,php自动给网址加上链接的方法,php网址链接方法_PHP教程
  5. 【leetcode】443. String Compression
  6. 6 交换机-topic类型
  7. UE4 中文文档阅读
  8. 自动化运维原来如此简单之工具建设
  9. c语言指针学多久,C语言指针难学吗?
  10. Vue+ant-design-pro(2)动态路由
  11. map的put 方法的返回值 null
  12. uniapp 小于1000 按原数字显示 超过1000 数字换算成10w+ 1.3k+ 显示
  13. 求2!+4!+6!+ …… +2n!的和
  14. [BZOJ4605]崂山白花蛇草水(主席树套kd-tree)
  15. 计算机无法外接投影,笔记本电脑连接投影仪无信号解决步骤
  16. 逻辑代数的基本定理和规则
  17. 【秋招纪实录】一篇特别正经的【无领导小组讨论】经验分享
  18. 脑电EEG常用的特征
  19. sip gw功能包括_全面解读SiP
  20. 增长黑客系列—如何精细化渠道效果投放

热门文章

  1. 数论--费马小定理求逆元
  2. ACM-ICPC 2019 山东省省赛 C Wandering Robot
  3. 结构体中的自然对界法则
  4. linux命令之watch -- 周期性地执行命令
  5. 嵌入式linux通过DHCP自动获取IP地址实现
  6. 计算机1级 计算机基础知识,计算机一级计算机基础及MSOffice应用:计算机基础知识...
  7. oracle将查询结果声明为伪表,Oracle的伪列和伪表
  8. 云原生的本质_云原生是什么 云原生技术有何作用
  9. python有没有帮助_没想到,python给我的帮助竟然这么大
  10. python 工资管理软件_4_python之路之模拟工资管理系统