【hibernate】Hibernate中get()和load()的区别
Hibernate中根据Id单条查询获取对象的方式有两种,分别是get()和load(),来看一下这两种方式的区别。
1. get()
使用get()来根据ID进行单条查询:
1
|
User user=session.get(User. class , "1" ); |
当get()方法被调用的时候就会立即发出SQL语句:
1
2
3
4
5
6
7
8
9
10
11
|
Hibernate: select user0_.ID as ID1_1_0_, user0_.CREATETIME as CREATETI2_1_0_, user0_.UPDATETIME as UPDATETI3_1_0_, user0_.USERNAME as USERNAME4_1_0_, user0_.PASSWD as PASSWD5_1_0_ from USER user0_ where user0_.ID=? |
并且返回的对象也是实际的对象:
使用get()和普通的单条查询并没有多大的区别。
2. load()
当使用load()进行查询的时候情况就变得很不一样了:
1
|
User user=session.load(User. class , "1" ); |
当调用load()方法的时候会返回一个目标对象的代理对象,在这个代理对象中只存储了目标对象的ID值,只有当调用除ID值以外的属性值的时候才会发出SQL查询的。
返回值:
在handler中有一个属性叫做target,保存着被代理的对象:
现在这个位置还是空的呢。
当我们尝试下面的代码时:
1
2
|
User user=session.load(User. class , "1" ); System.out.println(user.getId()); |
因为我们只访问了ID属性,这个在代理对象中是已经存在的了,所以并不需要再去数据库中查询,因此并不会发出SQL查询语句。
当使用到除ID以外的属性的时候,会发出SQL查询语句,比如尝试执行下面的代码:
1
2
|
User user=session.load(User. class , "1" ); System.out.println(user.getUsername()); |
会发现控制台打印了SQL查询语句:
1
2
3
4
5
6
7
8
9
10
11
|
Hibernate: select user0_.ID as ID1_1_0_, user0_.CREATETIME as CREATETI2_1_0_, user0_.UPDATETIME as UPDATETI3_1_0_, user0_.USERNAME as USERNAME4_1_0_, user0_.PASSWD as PASSWD5_1_0_ from USER user0_ where user0_.ID=? |
这个时候再看代理对象的话,会发现target已经被填充上了:
3. Exception
下面的代码会报一个空指针异常:
1
2
|
User user=session.get(User. class , "foobar" ); System.out.println(user.getUsername()); |
上面的这段代码抛出了空指针异常 NPE:
这个是很容易理解的,因为没有查询到的就空指针了嘛。
而下面的这段代码则会报一个ObjectNotFoundException异常:
1
2
|
User user=session.load(User. class , "foobar" ); System.out.println(user.getUsername()); |
抛出了ObjectNotFoundException异常:
这个就有点奇怪了,这个是因为我们使用load()的时候返回的是一个代理对象,因为这个时候还没有进行查询,所以我们并没有办法确定要查询的对象到底存在不存在,所以使用load()查询的返回值是永远不会为空的,但是呢,当我们试图访问被代理的真实对象的时候,因为这个对象并不存在,所以就抛出了一个ObjectNotFoundException。
还有一种说法是get()是用于不确定对象是否真的存在的情况,所以在查询出来后可以先进行一个空指针判断,而load()方法用于对象一定存在的情况下,不然等会儿使用的时候就可能会抛出ObjectNotFoundException了。
再来看下面这段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@Test public void test_001(){ SessionFactory sessionFactory= new Configuration().configure().buildSessionFactory(); Session session=sessionFactory.openSession(); User user= null ; try { session.beginTransaction(); user=session.load(User. class , "foobar" ); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); e.printStackTrace(); } finally { try { session.close(); } catch (Exception e) { e.printStackTrace(); } } System.out.println(user.getUsername()); } |
抛出了一个LazyInitializationException:
这个是因为我们使用load()查询出来的对象只有在调用完非ID属性的时候才会去查询数据填充进来,但是查询数据的时候是需要依赖产生这个代理对象的那个Session去查询的,当我们将Session关闭后,再试图去访问非ID属性,它正打算拿着自己依赖的Session去数据库查询,一看Session竟然被关闭了,得,干脆抛出一个LazyInitializationException好了。
解决办法就是在查询的时候思考一下,这个对象时候需要在Session关闭之后还能使用得到呢?如果是的话,那么我们使用get()来查询,或者手动调用空访问一个非ID属性让它把数据回填上先。
4. 缓存
get()和load()都会使用缓存,都是首先从一级缓存Session中查找,当找不到的时候再去二级缓存中查找,当查询不到的时候get()返回的是null,而load()则返回代理对象。
来看下面这段代码:
1
2
|
User user1=session.get(User. class , "1" ); User user2=session.load(User. class , "1" ); |
来看一下这两条执行过后这两个变量的值:
会发现两个都是真实对象,连load()返回的也是真实对象,并且它们引用的还是同一块对象。
这个是因为get()查询出来ID为1的对象后会将其放入到缓存中,而load()再去查询的时候它会先去缓存中查找,如果缓存中没有的话才会返回代理对象,但是当缓存中已经存在的话就直接将真实对象返回来了。
5. 对比总结
返回值:
get()返回的是查询出来的实体对象,而load()查询出来的是一个目标实体的代理对象。
查询时机:
get()在调用的时候就立即发出SQL语句查询,而load()在访问非ID属性的时候才会发出查询语句并且将被代理对象target填充上,但是如果这个动作发生在Session被关闭后的话就会抛出LazyInitializationException。
查询结果为空时:
get()抛出NullPointerException
load()抛出ObjectNotFoundException
转载:https://www.cnblogs.com/cc11001100/p/6883790.html
【hibernate】Hibernate中get()和load()的区别的更多相关文章
- Hibernate中get()和load()方法区别
get和load方式是根据id取得一个记录下边详细说一下get和load的不同,因为有些时候为了对比也会把find加进来. 1.从返回结果上对比:load方式检索不到的话会抛出org.hibernat ...
- Hibernate中get()和load()的区别
Hibernate中根据Id单条查询获取对象的方式有两种,分别是get()和load(),来看一下这两种方式的区别. 1. get() 使用get()来根据ID进行单条查询: User user=se ...
- Hibernate中get()与load()的区别,以及关于ThreadLocal的使用方法
一.get方法和load方法的简易理解 (1)get()方法直接返回实体类,如果查不到数据则返回null.load()会返回一个实体代理对象(当前这个对象可以自动转化为实体对象),但当代理对象被调用时 ...
- Hibernate中Session.get()/load()之区别
原文链接http://sunxin1001.iteye.com/blog/292090 Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象.其区 ...
- Hibernate 中 get()和load()的区别
一.1.程序检索数据库中不存在的OID: load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常 get方法检索不到的话会返回nu ...
- Hibernate中get和load的区别
get获取的对象立即执行sql查询数据库中当前实体表中的数据,如果外键关联的其他实体表如果配置了懒加载关闭,则也会查询出外键关联的其他实体表中的数据,否则外键关联的其他实体表则以代理对象表示(称其为代 ...
- hibernate延迟加载之get和load的区别
在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种就是通过session.load()方法,然后其实这两种方法在获得一个实体对 ...
- hibernate的get方法和load方法区别
读者需注意:Hibernate版本不同,运行机制不太一样,以下是hibernate3.x作为讲解 get方法: Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然 ...
- DOM加载过程中ready和load的区别
在浏览器地址栏输入URL地址,浏览器开始加载页面时,有以下几个过程 1.浏览器开始解析HTML文档 2. 浏览器遇到HTML文档中的<script>元素以及CSS样式文件,并且没有asyn ...
随机推荐
- 持续化集成Jenkins的系统配置
最近在研究selenium2自动化测试,用到持续化集成jenkins.由于之前仅限于使用,而没有真正动手配置过,所以现在学习从零开始,搭建持续化集成,故而有了这篇博客. 先介绍一下项目持续集成测试,这 ...
- Django 二——models(admin、ORM),一对一、一对多、多对多操作,all、values、value_list的对比
内容概要 1.关系对象映射ORM 2.admin的配置(选修) 3.all().values().value_list()的对比 4.数据库操作(一对一.一对多.多对多) 5.HttpResponse ...
- 什么是Maven?
Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. 发文时,绝大多数开发人员都把 Ant 当作 Java 编程项目的标准构建工具.遗憾的是, ...
- Leetcode33--->Search in Rotated Sorted Array(在旋转数组中找出给定的target值的位置)
题目: 给定一个旋转数组,但是你不知道旋转位置,在旋转数组中找出给定target值出现的位置:你可以假设在数组中没有重复值出现 举例: (i.e., 0 1 2 4 5 6 7 might becom ...
- webapi同时支持post和get报404错误
文章:webapi设置一个Action同时支持get和post请求 这篇文章,有提供方法.参数前加上[FromUri] [AcceptVerbs("GET", "POST ...
- 后台线程读取指定的web.config
//读取配置文件,订单地址修改接口地址 ExeConfigurationFileMap configMap = new ExeConfigurationFileMap(); configMap.Exe ...
- JDBC初探(一)
下载好JDBC之后,首先做的应该是查看它的文档 打开connector-j.html import java.sql.Connection; import java.sql.DriverManager ...
- Thinkphp5.1手册太简单,有的功能用起来不确定结果是否和预料的一样,顾整理记录
//模板{if false} 1 {else/} //====>可以使用 效果同 {else /} 2 {/if} {if condition="(1 eq 1) and false& ...
- SQLSERVER中文日期varchar格式转换成datetime格式
因项目要求,需要把SQLSERVER一张客户表的数据同步到oracle库的一张客户表,但两张表有时间类型不一致,需要进行转换 如下: SELECT CUSTCODE,AgreementValidity ...
- 【Luogu】P3787冰精冻西瓜(线段树)
题目链接 我脑子怕不是有坑qwqqq 用前缀和思想,dis[i]表示i离根的距离,那么修改操作其实是对x的子树区间加y/dis[x],查询的时候*dis[to]即可. 对付/0错的思路是建森林,然而这 ...