通过看孙卫琴的精通Hibernate和平时自己的使用,对他的几种检索策略有了更深的认识,再次总结一下
问题的引出:
Customer和Order的经典一对多场景<o:p></o:p>
Customer表
<o:p>
ID<o:p></o:p>
|
ORDER_NUMBER<o:p></o:p>
|
CUSTOMER_ID<o:p></o:p>
|
1<o:p></o:p>
|
Tom_order001<o:p></o:p>
|
1<o:p></o:p>
|
2<o:p></o:p>
|
Tom_order002<o:p></o:p>
|
1<o:p></o:p>
|
3<o:p></o:p>
|
Mike_order001<o:p></o:p>
|
2<o:p></o:p>
|
4<o:p></o:p>
|
Jack_order001<o:p></o:p>
|
3<o:p></o:p>
|
5<o:p></o:p>
|
TLinda_order001<o:p></o:p>
|
4<o:p></o:p>
|
6<o:p></o:p>
|
Unknown_order001<o:p></o:p>
|
null<o:p></o:p>
|
</o:p>
Oder表<o:p></o:p>
ID<o:p></o:p>
|
NAME<o:p></o:p>
|
1<o:p></o:p>
|
Tom<o:p></o:p>
|
2<o:p></o:p>
|
Mike<o:p></o:p>
|
3<o:p></o:p>
|
Jack<o:p></o:p>
|
4<o:p></o:p>
|
Linda<o:p></o:p>
|
在Session缓存中存放的就相互关联的对象图,从数据库中加载Customer时,会同时加载所有关联的Order对象,这就产生了如下问题:<o:p></o:p>
当执行session的find方法查询所有customer对象时<o:p></o:p>
java 代码
- List customers = session.find(“from Customer as c”);
运行find方法时,Hibernate将先查询CUSTOMERS表中的所有记录,然后根据记录ID到ORDER表里查询相关的记录.Hibernate依次执行一下select语句:<o:p></o:p>
sql 代码
- 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对象.Hiberante在检索语customer关联的Order对象时使用了默认的立即检索策略,这种方式存在两大缺点<o:p></o:p>
1. select语句太多,频繁访问DB会影响检索性能.如果需要查询n个Customer对象,那么必须执行n+1次select语句,这种检索策略没有利用sql的连接查询功能,<o:p></o:p>
如以上5条语句可以用1句左外连接来完成<o:p></o:p>
<o:p>
sql 代码
- select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID=ORDERS.CUSTOMERS_ID
查询出了所有CUSTOMERS表所有记录和匹配的ORDERS表记录<o:p></o:p>
2.如果只需要访问Customer对象,不需要Order对象时,加载Order对象时多余的操作,而且浪费了许多内存空间.<o:p></o:p>
<o:p> Hibernate的三种检索策略,为了解决立即检索的问题,Hibernate提供了其他两种检索策略,即延迟和迫切左外连接检索.</o:p>
<o:p>
一.立即检索<o:p></o:p>
Hibernate的默认检索策略,当执行session 的查询方法时,会把相关联的表的数据全部查询出来.
二延迟检索<o:p></o:p>
包括类级别和集合级别的延迟加载.<o:p></o:p>
1.类级别<o:p></o:p>
某个类采用延迟加载<o:p></o:p>
<class name="”…’" lazy="”true”"></class><o:p></o:p>
只和session的load方法有关,执行load方法时仅返回Customer的代理类实例.<o:p></o:p>
代理类实例有一下特征<o:p></o:p>
1)有Hibernate动态生成,扩展了Customer类,因此它继承了Customer的所有属性和放,但对于应用程序是透明的.<o:p></o:p>
2)词代理类实例仅初始化了OID属性,其他属性为null,因此它占的内存很少<o:p></o:p>
3)第一次访问代理类实例的属性(除了OID属性,它已有值)时, Hiberante会初始化此实例,产生select语句.<o:p></o:p>
注:Hibernate采用CGLIB工具来生成持久化类的代理类CGLIB是一个功能强大的JAVA字节码生成工具,它能在程序运行时动态生成扩展Java类或者实现Java接口的代理类.关于CGLIB的更多信息,可到网站http://cglib.sourceforge.net了解.,<o:p></o:p>
2.集合级别<o:p></o:p>
当不使用相关表的数据时, 在Custom映射文件中set属性设置的 lazy="true",此时不会立即检索相关表,
需注意<o:p></o:p>
1)并没有创建Order代理类实例,也无法创建因为还不知道与Customer关联的所有Order对象的OID.这时Customer的orders属性引用的是Hibernate提供的集合代理类实例.<o:p></o:p>
2)当应用程序第一次要使用相关表的数据时,才从DB的相关表中检索相关数据。<o:p></o:p>
3)只有当集合代理类的实例处于持久化状态时,才可以初始化,以后才可使用,否则会抛出延迟初始化错误:ERROR:LazerInitiater:63........<o:p></o:p>
三.迫切左外连接<o:p></o:p>
默认情况下,多对一关联采用的方法。如果把映射文件的<many-to-one></many-to-one>many-to-one元素outer-join 值设为"true",则总是采用此策略。<o:p></o:p>
Hibernate允许在应用程序的HQL语句中显示指定迫切左外连接检索,它会覆盖配置文件的检索策略。<o:p></o:p>
如
- session.find(" from Customer as c where c.id=1 " );
-
- session.find(" from Customer as c left join fetch c.orders where c.id=1 " )
第一句会采用映射文件中的检索策略,而第二句会覆盖映射文件的策略。
下面是三种检索策略的比较
检索策略
|
优点
|
缺点
|
优先使用场合
|
立即检索
|
1) 对应用程序透明,不管对象在持久化或游历状态.应用程序都可以方便的从一个对象导航到与它关联的对象
2) Sql简单,速度快
|
3) select语句数目太多
4) 可能会加载与不需要访问的对象,浪费内存空间
|
1) 类级别
2) 应用需立即访问的对象
3) 使用了二级缓存
|
延迟检索
|
1) 有程序决定需要加载那些对象,避免多余的select语句
2) 避免加载不需要访问的对象,节省内存空间,提高检索性能
3) Sql简单,速度快
|
应用如果访问游历的代理类实例,必须保证它在持久化状态时已被初始化
|
1) 一对多或多对多
2) 应用不会立即或根本不会访问的对象.
|
迫切左外连接
|
1) 对应用程序透明,不管对象在持久化或游历状态.应用程序都可以方便的从一个对象导航到与它关联的对象
2) 使用了外连接,select语句少,减少访问数据库频率
|
1) 可能会加载不必要的对象,浪费空间
2) 如果表连接过于负责,sql负责度高,,会影响性能
|
1) 多对一或一对一
2) 应用会立即访问的对象
3) 数据库具有良好的表连接性能
|
|
总之,对于实际的应用,为了选择合适的检索策略,需要测试应用程序的各个用例,跟踪使用不用检索策略时Hibernate执行的sql语句,可以百Hibernate的配置文件的showsql属性设为true,输出sql。根据特定的关系模型,比较查询性能。
到底是使用外连接查询快,
sql 代码
- select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID=ORDERS.CUSTOMERS_ID where CUSTOMERS.ID=1
还是分开的select语句快
sql 代码
- select * from CUSTOMERS
- select * from ORDERS where CUSTOMER_ID=1
不断的调解检索策略,以便在减少select语句和将少select语句复杂度之间找到平衡点,获得最佳的检索性能。
</o:p></o:p>
分享到:
相关推荐
基于springboot教育资源共享平台源码数据库文档.zip
linux开发篇,配套视频:https://www.bilibili.com/list/474327672?sid=4493702&spm_id_from=333.999.0.0&desc=1
ReadEra 这个阅读应用能够打开下列任何格式的文档: EPUB, PDF, DOC, RTF, TXT, DJVU, FB2, MOBI, 和 CHM. 基本上来说,你可以用它阅读你的设备内存中的任何书籍或者文本文档。 这个应用与划分成章节的文档兼。,有一个书签功能,可以在你阅读的时候,自动保存你的进度。另外,它让你更改页面模式,从几种不同的主题中进行挑选(夜间,白天,棕黑色调,还有控制台)。
软件环境:KEIL4 硬件环境:STM32单片机+舵机 控制原理:通过控制输出信号的占空比调节舵机旋转的角度
基于springboot仓库管理系统源码数据库文档.zip
酒店管理系统源码C++实现的毕业设计项目源码.zip,个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分98.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 酒店管理系统源码C++实现的毕业设计项目源码.zip,酒店管理系统源码C++实现的毕业设计项目源码.zip个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分98.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。酒店管理系统源码C++实现的毕业设计项目源码.zip酒店管理系统源码C++实现的毕业设计项目源码.zip酒店管理系统源码C++实现的毕业设计项目源码.zip,个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分98.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。酒店管理系统源码C++实现的毕业设计项目源码.zip,个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分98.5分。主要针对计算机相关专业的正在做毕
58商铺全新UI试客试用平台网站源码
springboot vue3前后端分离 基于SpringBoot+Vue的轻量级定时任务管理系统.zip
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
4D毫米波雷达点云数据处理方法研究.caj
S M 2 2 5 8 X T 量产工具供大家下载使用
基于springboot的文物管理系统源码数据库文档.zip
基于springboot的电影院售票管理系统源码数据库文档.zip
基于Java web 实现的仓库管理系统源码,适用于初学者了解Java web的开发过程以及仓库管理系统的实现。
美容美发项目,使用django框架,前后端一体化项目
在线票务:2023年中国在线票务行业市场规模约为24.99亿元,挖掘市场蓝海新机遇 在数字浪潮的席卷下,传统的票务销售模式正经历着前所未有的变革。纸质门票逐渐淡出人们的视野,取而代之的是便捷、高效的数字和移动票务。这一转变不仅为消费者带来了前所未有的购票体验,更为在线票务平台开辟了广阔的发展空间和市场机遇。随着国民经济的持续增长和文体娱乐行业的蓬勃发展,中国在线票务行业正站在时代的风口浪尖,等待着每一位有志之士的加入。那么,这片蓝海市场究竟蕴藏着怎样的潜力?又该如何把握机遇,实现突破?让我们一同探索。 市场概况: 近年来,中国在线票务行业市场规模持续扩大,展现出强劲的增长势头。据QYResearch数据显示,2023年中国在线票务行业市场规模约为24.99亿元,尽管受到宏观经济的影响,市场规模增速放缓,但整体趋势依然向好。这一增长主要得益于国民人均收入的不断提高、电影及演出行业的快速发展以及政府政策的支持。例如,2023年财政部、国家电影局发布的《关于阶段性免征国家电影事业发展专项资金政策的公告》,为电影行业注入了强劲动力,进而推动了在线票务市场规模的扩大。 技术创新与趋势: 技术进步
基于SpringBoot的养老院管理系统源码数据库文档.zip
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
内容概要:本文档是一份详细的Go语言教程,从基础概念介绍到高级主题均有覆盖。主要内容包括Go语言的基础语法、数据类型、控制结构、函数、结构体、接口和并发编程等方面。通过具体示例介绍了如何使用Go语言进行开发。 适合人群:初学者和有一定经验的程序员都可以从这篇教程中受益,特别是那些想要快速掌握Go语言并应用于实际项目的开发者。 使用场景及目标:适用于初学者系统学习Go语言的基础知识和常用功能;也可以作为已有开发经验者的参考资料,帮助他们解决具体的编程问题,提高开发效率。 其他说明:本教程不仅包含了Go语言的基本知识点,还重点讲解了其独特的并发编程模型。读者在学习过程中应该注重理论与实践相结合,通过实际编写代码来加深理解和记忆。
基于springboot计算机基础网上考试系统源码数据库文档.zip