Hibernate框架对检索进行了优化,前面我们将CURD的时候提到了load和get的区别,当时仅仅说了load为延迟加载,get为立即加载,当检索的记录为空的时候load报错(不是在执行load方法的时候报的错,是执行后面的操作报的错),get返回null。

其实load就是对检索的一种优化,它的作用是当程序执行检索代码的时候,在缓存中没有的前提下,不会立即去数据库中查询,而是等真正用到的时候才会去查询,这是一种懒加载策略。

下面我们要讲的内容有:

  • 当前对象的检索优化
  • 关联对象的检索优化

当前对象的检索优化:

当前对象:这个概念存在于单表查询,可以认为是我们直接查询的对象(多表查询中我们有关联查询)。

当前对象的检索优化很简单,就是我们不使用get进行查询,使用load进行查询。我们的映射配置文件中有一个属性就是用来设置懒加载的:



这个lazy属性默认是true(我们不设置的时候),即当我们使用load进行查询的时候是进行懒加载的,当配置文件设置lazy设置为false的时候,即使使用load也是立即加载,还有一个为extra叫做特懒加载(能用聚合函数查询就不进行详情查询)。

上面就是对当前对象的检索优化,很简单。

但是我们要知道load底层的原理是什么,为什么当查询的记录不存的时候会报错:

Hibernate的load是通过动态代理获得我们想要查询的对象的,当执行load时候,它获得的是代理类对象,此时并没有真正执行查询语句,当真正需要数据的时候(例如前台请求,或者我们测试的时候输出结果),查询语句才会执行。所以当我们执行查询语句的时候才会真正调用真实对象的查询方法,并为代理对象初始化(需要查询的值)。

为啥会出错呢?

我们来看看出错的地方:

这个是实现动态代理类的invoke方法:

public Object invoke(
final Object proxy,
final Method thisMethod,
final Method proceed,
final Object[] args) throws Throwable {
if ( this.constructed ) {
Object result;
//调用父类的invoke方法
result = this.invoke( thisMethod, args, proxy );
//处理特殊返回结果
if ( result == INVOKE_IMPLEMENTATION ) {
//最重要,这里最终会调用到获取最终数据的方法
Object target = getImplementation();
......
//使用反射调用最终对象的最终方法,如xxx.getName()之类
returnValue = thisMethod.invoke( target, args );
}
public final Object getImplementation() {
initialize();//初始化对象,或者叫实例化对象
return target;
} public final void initialize() throws HibernateException {
if (!initialized) {
target = session.immediateLoad(entityName, id);//调用session,立即加载相应对象
initialized = true;
checkTargetState();//这个方法检查是否为空
}
}
private void checkTargetState() {
if ( !unwrap ) {
if ( target == null ) {
getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( entityName, id );//这里就是报错的根源
}
}
}

以上的具体分析在我查到的一篇博客内有详细解答:

https://www.iflym.com/index.php/code/201112050001.html

关联对象的检索优化:

关联对象的检索优化分为两种:

  • 多端加载优化
  • 单端加载优化

我们先来说多端加载优化(我们下面所说的对一方查询都是使用HQL):

所谓多端关联加载对象是指一方为主加载对象,而多端为从加载对象,对于多方加载时所进行的延迟加载配置。

既然是“一”方为主加载对象,那么就需要在“一”方进行配置,在进行配置之前我们先来看两组属性:



lazy我们都知道,fetch是什么呢(字面意思是:拿来取来)。

这个是fetch在配置文件中的位置,是set标签内的属性



①当它为join的时候采用迫切左外连接(是立即加载,当配置这个属性的时候lazy失效)。当查找一方的时候因为我们使用的是左外连接(多表查询),所以效率上肯定比查找两张表的速度更快,即当查询一方的时候,多方的详情数据也被查询出来了。

②当fetch为select时,lazy为false时,采用普通select查询,当查询一方的时候,也会顺带将多方检查了,且都是通过直接查询加载的方式;lazy为true时,先查一方,多方为懒加载。

③当fetch为subselect时候,如果“一”里面有很多条记录,例如有三个部门,每个部门里面有十个员工,如果fetch为select,当遍历这些部门和员工的时候,每次都要先查询部门,然后再查询员工;但是如果使用子查询的话(fetch=“subselect”),只会查询一次部门详情,后面查询员工的时候不用再次查询部门,因为部门作为子查询进行。

说完多端加载优化我们再来说单端加载优化:

单端加载优化和多端加载优化用到的是同样的属性,但是它的属性取值不同且,配置是放在多方的。





单端的配置在many-to-one标签中配置fetch

①当fetch=“join”时,和多端一样,lazy失效,使用的是迫切左外连接。

②当fetch=“select”时也是采用普通select查询。

当lazy为proxy时候和no-proxy,它们的使用决定代理方式(懒加载方式),是否为懒加载还要看“一”方的配置。

关于检索优化就说到这里。

如有错误,不灵赐教。

Hibernate学习---检索优化的更多相关文章

  1. [原创]java WEB学习笔记89:Hibernate学习之路-- -Hibernate检索方式(5种),HQL介绍,实现功能,实现步骤,

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. Hibernate学习---缓存机制

    前言:这些天学习效率比较慢,可能是手头的事情比较多,所以学习进度比较慢. 在之前的Hibernate学习中,我们无论是CURD,对单表查询还是检索优化,我们好像都离不开session,session我 ...

  3. Hibernate学习笔记(二)

    2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...

  4. Hibernate学习笔记(一)

    2016/4/18 19:58:58 Hibernate学习笔记(一) 1.Hibernate框架的概述: 就是一个持久层的ORM框架. ORM:对象关系映射.将Java中实体对象与关系型数据库中表建 ...

  5. Hibernate学习之面试问题汇总

    1. Hibernate 的检索方式有哪些 ? ① 导航对象图检索 ② OID检索 ③ HQL检索 ④ QBC检索 ⑤ 本地SQL检索 2. 在 Hibernate 中 Java 对象的状态有哪些 ? ...

  6. Hibernate 学习笔记 - 2

    五.映射一对多关联关系 1. 单向多对一 即 单向 n-1 1)单向 n-1 关联只需从 n 的一端可以访问 1 的一端 ① 域模型: 从 Order 到 Customer 的多对一单向关联需要在Or ...

  7. Hibernate5笔记6--Hibernate检索优化

    Hibernate检索优化: 检索即查询.为了减轻DB的访问压力,提高检索效率,Hibernate对检索进行了优化. 所谓检索优化,指的是对查询语句的执行时机进行了细致.严格的把控:并不是代码中一出现 ...

  8. Hibernate学习之——搭建log4j日志环境

    昨天讲了Hibernate开发环境的搭建以及实现一个Hibernate的基础示例,但是你会发现运行输出只有sql语句,很多输出信息都看不见.这是因为用到的是slf4j-nop-1.6.1.jar的实现 ...

  9. Hibernate的检索方式

    Hibernate的检索方式 检索方式(查询的方式) 导航对象图检索方式: 根据已经加载的对象导航到其他对象 Customer customer = (Customer)session.get(Cus ...

随机推荐

  1. NGINX扩展

    https://github.com/cuber/ngx_http_google_filter_module

  2. Spring Boot全日志设置

    说在前面 这里日志分两种.一种是tomcat的输出(系统)日志,一种是自己定义的日志. 系统日志设置 目标 当springboot接收到请求时记录日志到文件中 实现 你只需要在你的绿叶applicat ...

  3. Linux 部署jenkins + svn + mavne + tomcat8自动化部署

    1,下载Jenkins  war包   官网下载地址 https://jenkins.io/ 2.初始化安装 1)首次启动jenkins,出于安全考虑,jenkins会生成一个随机的口令到 /root ...

  4. PHP测试与优化(1)-- Apache自带的压力测试工具ab(apache bench) - 简单使用

    ab是apache自带的网站压力测试工具,能够测试网站在一定时间内的发生高并发时的反应. 使用 1.进入apache的bin文件夹 2.模拟并发级别为100,请求数为1000个的api数据请求数量测试 ...

  5. 基于JS实现回到页面顶部的五种写法(从实现到增强)

    这篇文章主要介绍了基于JS实现回到页面顶部的五种写法(从实现到增强)的相关资料,本文介绍的非常详细,实用性也非常高,非常具有参考借鉴价值,需要的朋友可以参考下   写法 [1]锚点 使用锚点链接是一种 ...

  6. NDK 安装小结

    建议先看后面的错误,可以先执行那些命令以免出现相关问题. chmod a+x android-ndk-r10c-linux-x86_64.bin ./android-ndk-r10c-linux-x8 ...

  7. Servlet 发送电子邮件

    使用 Servlet 发送一封电子邮件是很简单的,但首先您必须在您的计算机上安装 JavaMail API 和 Java Activation Framework)JAF). 您可以从 Java 网站 ...

  8. ionic2常见问题-启动后白屏问题

    问题描述 app启动后大概有几秒白屏,才会显示首页,如下gif图 启动有白屏.gif 解决方法1 请查看以下3张图的标注 图 1-最初config.xml配置 图 2-更改后的splash配置 图 3 ...

  9. ROS导航之地图costmap_2d与bresenham算法

    读者可以参读http://wiki.ros.org/costmap_2d   costmap_2d: 无论是激光雷达还是如kinect 或xtion pro深度相机作为传感器跑出的2D或3D SLAM ...

  10. 26计算限制的异步操作02-CLR

    由CLR via C#(第三版) ,摘抄记录... 6 Parallel的静态For,ForEach和Invoke方法 在一些常见的编程情形中,使用任务也许会提升性能.为了简化编程,静态类System ...