Hibernate中的Session.load() 和 Session.get() 的区别

文章目录

在这里插入图片描述

执行语句 session.load(UserInfoBean.class,2) 会先在一级缓存中找 id=2 的 UserInfoBean 对象(看红色线条),找不到去二级缓存找,还找不到就不找了,直接获取一个代理对象并返回该对象。当需要获取代理对象中的属性值时,则直接去数据库查(看蓝色线条),就是所谓的懒加载。

执行语句 session.get(UserInfoBean.class,2),由于 load 方法已经查过 id=2 这个对象,所以这个对象(其实是一个代理对象)已经保存在缓存中了,因此 get() 方法可以在缓存区中直接获取到这个对象(看灰色线条)。

执行语句 session.get(UserInfoBean.class,3) ,由于 id=3 这个对象没有查过,get() 方法先去一级缓存中找 id=3 的对象(看紫色线条),找不到去二级缓存找,还找不到就去数据库找。

相同点

1.两个方法均可以根据指定的实体类和 id 从数据库读取记录,并返回与之对应的实体对象。

代码如下:

session.load(Employee.class,1);
session.get(Employee.class,1);

2.两个方法都支持缓存机制,即先到一级缓存区获取数据;若没有则到二级缓存区获取数据;还是没有则访问数据库获取数据。

区别

1.如果未能发现符合条件的记录(即数据库不存在指定 id 的记录),get() 方法返回 null,而 load() 方法会抛出一个 ObjectNotFoundException。

// 对应的数据表中并不存在id=2的记录
Employee employee = session.get(Employee.class, 2);
System.out.println(employee);// null

load() 会返回的是一个实体代理对象,那么该代理对象在执行 getXxx() 时,会直接去 DB 中查找数据,如果查找不到数据,就会抛出ObjectNotFoundException 异常。

扫描二维码关注公众号,回复: 14354959 查看本文章

2.load() 方法支持懒加载机制(延迟加载机制),get() 不支持懒加载机制

类名.hbm.xml 配置文件 <class> 元素的 lazy 属性设置为 true 时(默认为 true),调用 load() 方法时 load() 先到缓存(session缓存/二级缓存)中去查,如果没有则返回一个代理类实例(不马上到 DB 中去找),这个代理类是运行时动态生成的,是实体类的子类。该代理类实例包括原目标对象(实体对象)的所有属性和方法,该代理类实例的属性除了 ID 有值外,其它属性都是默认值。查看日志并没有 Hibernate SQL 输出,说明没有执行查询操作。当代理类实例通过 getXXX() 方法获取属性值时,Hiberante 才到 DB 中查询数据。

类名.hbm.xml 配置文件 <class> 元素的 lazy 属性设置为 false 时,调用 load() 方法与调用 get() 的效果相同,即只会返回实体类实例,并不返回代理类实例。而调用 get() 方法时不管 lazy 为何值,都直接返回实体类实例。get() 先到缓存(session缓存/二级缓存)中去查,如果没有就到 DB 中去查(即马上发出 sql)。

疑问:
当开启懒加载机制后,load() 是先去缓存区(一级/二级缓存)中查找对象,找到则返回给对象,找不到则返回一个代理对象,还是说不会去缓存区查找对象,而是直接返回代理对象呢?或者说 load() 方法首先查询session缓存,没有就创建代理对象,实际使用数据时才查询二级缓存和数据库,是这样吗?

代理对象:
在 Hibernate 中,所谓代理对象就是依据指定的类型和给定的 ID 值(标识符值/Identifier)动态生成的虚假对象(伪对象)。该对象中除了 ID,其它属性则初始化为默认值

注意点:
get 方法如果在 session缓存中找到了指定 id 对应的对象,如果刚好该对象前面是被代理过的(如被 load 方法使用过,或者被其他关联对象延迟加载过),那么返回的还是原先的代理对象,而不是实体类对象;如果该代理对象还没有加载实体数据(就是 id 以外的其他属性数据),那么会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。

猜你喜欢

转载自blog.csdn.net/liaowenxiong/article/details/125580745