Hibernate中get和load区别
get数据加载
语法
Session调用get方法,通过对象的反射创建出对应的实体对象
session.get(类名.class,主键id的值);
代码示例:
使用junit和debug断点追踪
查看代码执行的日志
通过最后一条记录,也就是断点处,我们可以看到,Hibernate向数据库发送了一条sql语句。
这条sql语句实际上就是用来查找对应id的那条记录。
同时我们看到,自动生成了User对象,并将记录中各个字段的值设到User对象的属性中。
通过上图发现,此时Session的map中有User对象的值,而临时集合为空。
这表明:User已经纳入Session管理,进入持久态;发送sql语句后临时集合被清空。
那么,如果没有找到对应id的记录,执行结果又会怎么样呢?
我们将id设为空串:
查看运行记录
查看最后一条记录,首先肯定发送sql语句,到数据库中查询。
我们发现此时没有生成User对象
Session的缓存中也不可能有User对象相关的值
小结
Session一旦调用get方法:
- Hibernate发送sql语句,到类所对应的表中查找主键为id的记录;
- 如果数据库中不存在该记录,不会生成User对象,否则,生成User对象,并将记录中各个字段的值设到User对象的属性中;
- 调用get加载后,对象进入持久态。
补充说明
Hibernate是如何获得该类所对应的表的呢?
类有关表的信息都配置在一个叫:类名.hbm.xml文件中
Hibernate通过configuration找到hbm.xml文件,从而找到类所对应的表
示例:
hibernate.cfg.xml文件:
User.hbm.xml文件
load数据加载
语法
与get语法类似
session.load(类名.class,主键id的值);
代码示例
同样使用junit和debug断点追踪
查看执行日志:
可以清楚的看到:Hibernate没有向数据库发送sql语句。
Session缓存中为空
User对象中的属性值都为空。
但我们发现User对象实际上是存在的。
这是一个代理对象,它是User类的子类对象,继承了User类中的属性和方法。
此时,我们还注意到id下面的target 的值为null,关于target,我们马上就会谈到。
我们将断点下移,代理对象调用getName方法
代理对象一旦开始操作User中的属性,Hibernate自动发送sql语句,并将取得的结果打印出来。
我们看到User对象中的属性仍然为null,但此时target不再为空,而是指向了生成的目标对象User
由上图可知,由于发送了sql语句,临时集合insertion中的值为null,但Session的map中存储了对象的数据,这说明User对象纳入了Session管理,进入持久态。
那么,如果load没有找到对应id的记录,执行结果又会怎么样呢?
我们将id设为空串:
运行代码结果:
在发送查询sql语句后,出现了ObjectNotFoundException异常
小结
Session调用load方法后:
- 生成目标类的代理对象,不发送sql语句查询数据库;
- 一旦调用代理对象的方法:发送sql语句,判断this.target是否为null(target默认为null);
- 如果不为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
两种加载方式的不同点
get:
- 立即发送sql语句查找记录
- 如果查询不到记录,返回null
load:
- 不发送sql语句,只有对象被使用时才发送sql语句
- 如果查询不到记录,抛出objectNofoundException异常
说明:本文仅用作学习笔记,无其他用途,如有冒犯可联系本人删除