Hibernate中get和load区别

get数据加载

语法

Session调用get方法,通过对象的反射创建出对应的实体对象
session.get(类名.class,主键id的值);

代码示例:

使用junit和debug断点追踪

Hibernate中get和load区别
查看代码执行的日志
Hibernate中get和load区别
通过最后一条记录,也就是断点处,我们可以看到,Hibernate向数据库发送了一条sql语句。
这条sql语句实际上就是用来查找对应id的那条记录。
Hibernate中get和load区别
同时我们看到,自动生成了User对象,并将记录中各个字段的值设到User对象的属性中。
Hibernate中get和load区别
通过上图发现,此时Session的map中有User对象的值,而临时集合为空。
这表明:User已经纳入Session管理,进入持久态;发送sql语句后临时集合被清空。

那么,如果没有找到对应id的记录,执行结果又会怎么样呢?
我们将id设为空串:
Hibernate中get和load区别
查看运行记录
Hibernate中get和load区别
查看最后一条记录,首先肯定发送sql语句,到数据库中查询。
Hibernate中get和load区别
我们发现此时没有生成User对象
Hibernate中get和load区别

Session的缓存中也不可能有User对象相关的值

小结

Session一旦调用get方法:

  1. Hibernate发送sql语句,到类所对应的表中查找主键为id的记录;
  2. 如果数据库中不存在该记录,不会生成User对象,否则,生成User对象,并将记录中各个字段的值设到User对象的属性中;
  3. 调用get加载后,对象进入持久态

补充说明

Hibernate是如何获得该类所对应的表的呢?

类有关表的信息都配置在一个叫:类名.hbm.xml文件中
Hibernate通过configuration找到hbm.xml文件,从而找到类所对应的表

示例:
hibernate.cfg.xml文件:Hibernate中get和load区别
User.hbm.xml文件
Hibernate中get和load区别

load数据加载

语法

与get语法类似
session.load(类名.class,主键id的值);

代码示例

同样使用junit和debug断点追踪

Hibernate中get和load区别
查看执行日志:
Hibernate中get和load区别
可以清楚的看到:Hibernate没有向数据库发送sql语句。

Hibernate中get和load区别
Session缓存中为空

Hibernate中get和load区别
User对象中的属性值都为空。

Hibernate中get和load区别
但我们发现User对象实际上是存在的。
这是一个代理对象,它是User类的子类对象,继承了User类中的属性和方法。
此时,我们还注意到id下面的target 的值为null,关于target,我们马上就会谈到。

Hibernate中get和load区别
我们将断点下移,代理对象调用getName方法

Hibernate中get和load区别
代理对象一旦开始操作User中的属性,Hibernate自动发送sql语句,并将取得的结果打印出来。

Hibernate中get和load区别

我们看到User对象中的属性仍然为null,但此时target不再为空,而是指向了生成的目标对象User

Hibernate中get和load区别

由上图可知,由于发送了sql语句,临时集合insertion中的值为null,但Session的map中存储了对象的数据,这说明User对象纳入了Session管理,进入持久态

那么,如果load没有找到对应id的记录,执行结果又会怎么样呢?
我们将id设为空串:

Hibernate中get和load区别
运行代码结果:

Hibernate中get和load区别
在发送查询sql语句后,出现了ObjectNotFoundException异常

小结

Session调用load方法后:

  1. 生成目标类的代理对象,不发送sql语句查询数据库;
  2. 一旦调用代理对象的方法:发送sql语句,判断this.target是否为null(target默认为null);
  3. 如果不为null,直接通过this.target调用指定方法。如果this.target=null,将target指向新生成的目标对象:this.target = session.get(类名.class,主键),再通过this.target调用指定方法

补充说明

使用IDEA进行debug追踪,会出现load加载时无论如何都会发送sql语句查询数据库的现象,导致效果和get方法一致。

解决方法:

设置路径:File | Settings | Build, Execution, Deployment | Debugger | Data Views | Java

Hibernate中get和load区别

两种加载方式的不同点

get:

  • 立即发送sql语句查找记录
  • 如果查询不到记录,返回null

load:

  • 不发送sql语句,只有对象被使用时才发送sql语句
  • 如果查询不到记录,抛出objectNofoundException异常

说明:本文仅用作学习笔记,无其他用途,如有冒犯可联系本人删除