Session中load/get方法的详细区别
Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象。
其区别在于: 如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObjectNotFoundException。 Load方法可返回实体的代理类实例,而get方法永远直接返回实体类。
load方法可以充分利用内部缓存和二级缓存中的现有数据,而get方法则仅仅在内部缓存中进行数据查找,如没有发现对应数据,将越过二级缓存,直接调用SQL完成数据读取。
Session在加载实体对象时,将经过的过程: 首先,Hibernate中维持了两级缓存。第一级缓存由Session实例维护,其中保持了Session当前所有关联实体的数据,也称为内部缓存。而第二级缓存则存在于SessionFactory层次,由当前所有由本SessionFactory构造的Session实例共享。出于性能考虑,避免无谓的数据库访问,Session在调用数据库查询功能之前,会先在缓存中进行查询。首先在第一级缓存中,通过实体类型和id进行查找,如果第一级缓存查找命中,且数据状态合法,则直接返回。
之后,Session会在当前“NonExists(把无效的条件写成一个黑名单,既然无效,那么也没必要再查下去)”记录中进行查找,如果“NonExists”记录中存在同样的查询条件,则返回null。“NonExists”记录了当前Session实例在之前所有查询操作中,未能查询到有效数据的查询条件(相当于一个查询黑名单列表)。如此一来,如果Session中一个无效的查询条件重复出现,即可迅速作出判断,从而获得最佳的性能表现。
对于load方法而言,如果内部缓存中未发现有效数据,则查询第二级缓存,如果第二级缓存命中,则返回。
如在缓存中未发现有效数据,则发起数据库查询操作(Select SQL),如经过查询未发现对应记录,则将此次查询的信息在“NonExists”中加以记录,并返回null。
根据映射配置和Select SQL得到的ResultSet,创建对应的数据对象。 将其数据对象纳入当前Session实体管理容器(一级缓存)。 执行Interceptor.onLoad方法(如果有对应的Interceptor)。 将数据对象纳入二级缓存。 如果数据对象实现了LifeCycle接口,则调用数据对象的onLoad方法。 返回数据对象。
/** *//** * load()方法的执行顺序如下: * a):首先通过id在session缓存中查找对象,如果存在此id的对象,直接将其返回 * b):在二级缓存中查找,找到后将 其返回。 * c):如果在session缓存和二级缓存中都找不到此对象,则从数据库中加载有此ID的对象 * 因此load()方法并不总是导致SQL语句,只有缓存中无此数据时,才向数据库发送SQL! */
/** *//** * 与get()的区别: * 1:在立即加载对象(当hibernate在从数据库中取得数据组装好一个对象后 * 会立即再从数据库取得数据此对象所关联的对象)时,如果对象存在, * load()和get()方法没有区别,都可以取得已初始化的对象;但如果当对 * 象不存在且是立即加载时,使用get()方法则返回null,而使用load()则 * 抛出一个异常。因此使用load()方法时,要确认查询的主键ID一定是存在 * 的,从这一点讲它没有get方便! * 2:在延迟加载对象(Hibernate从数据库中取得数据组装好一个对象后, * 不会立即再从数据库取得数据组装此对象所关联的对象,而是等到需要时, * 都会从数据库取得数据组装此对象关联的对象)时,get()方法仍然使用 * 立即加载的方式发送SQL语句,并得到已初始化的对象,而load()方法则 * 根本不发送SQL语句,它返回一个代理对象,直到这个对象被访问时才被 * 初始化。 */
get()----不支持LAZY
load()----支持LAZY
load和get一共是2个区别 先讲第一个 延迟加载 load是true而get是false 意 思就是 load采用的是延迟加载的方式 而get不是,hibernate思想是 既然这个方法支持延迟加载 他就认为这个对象一定在数据库存在,在你 声明 TFaq tfag2=(TFaq)sess.load(TFaq.class, 300); 这句时候,hibernate就干了一件事 1.查询session缓存 2.缓存中没有这个对象 就创建个代理 因为延迟加载需要代理来执行 所以就创建了个代理 ok 到此为止 这句话就干了个这个 并没有去数据库交互查询 当你使用这个对象 比如tfag2.getTfRtitle()或get方法时候 这个时候 hibernate就去查询二级缓存和数据库,数据库没有这条数据 就抛出异常 整个load方法调用结束 load没什么神奇 这就是他干过所有的事情
load方法讲完了 我在讲一下get方法工作原理 因为hibernate规定get方法不能使用延迟加载 所以和load还是不一样的 TFaq tfag2=(TFaq)sess.get(TFaq.class, 300); 在创建这条语句时候 我们看看hibernate干了哪些事 1.get方法首先查询session缓存 (session缓存就是hibernate的一级缓存 这个概念大家应该清楚吧 ) 2.get方法如果在session缓存中找到了该id对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是原先的代理对象,而不是实体类对象。 3.如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。 (这个代理实际就是空的对象 并没有去数据库查询得到的 我们叫代理对象,如果 去数据库查询了 返回到了这个对象 我们叫实体对象 就是这个对象真实存在)
我在总结性一句话这2者区别 get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库
----我测试过:
在使用session.get方法后如果把session关闭的话,也会出现懒加载异常。
那么只有在manytoone标签里配置 lazy="false"时异常才会解决。
也就是说上面转载的第3条不是那么正确:返回该代理对象不错,但是如果该对象没有加载实体数据,那么也会在用到时才会加载,即不会立即查询数据库或者二级缓存,那么你现在把session关闭,这个对行啊没有加载实体数据----才会出现懒加载异常。
装载自:http://blog.csdn.net/houjiyu243042162/article/details/27243029
Session中load/get方法的详细区别的更多相关文章
- Session中清除对象方法比较
转载. https://blog.csdn.net/u014401141/article/details/51816308 Session中清除对象方法比较 http://blog.csdn.ne ...
- java中的compareto方法的详细介绍
java中的compareto方法的详细介绍 Java Comparator接口实例讲解(抽象方法.常用静态/默认方法) 一.java中的compareto方法 1.返回参与比较的前后两个字符串的as ...
- session中load()跟get()的区别
1.相同点:Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象. 2.区别在于: (1)如果未能发现符合条件的记录,get方法返回null,而l ...
- Hibernate session中的createCriteria方法
在应用中获取session对象: Session session= HibernateUtil.getSession(); List list=session.createCriteria(Mete ...
- java中的static方法和实例方法区别
1.static方法是大家共享的资源,放在内存堆中,比如村里的河水,每个人都可以取,而且不管你创建多少个实例,该方法在内存中只有一个,节省内存空间, 而且访问速度也是比较快的. 2.实例方法就不同,它 ...
- php中的var_dump()方法的详细说明
首先看看实例: <?PHP$a = "alsdflasdf;a";$b = var_dump($a);echo "<br>";//var_du ...
- java.lang.String中的trim()方法的详细说明(转)
String.Trim()方法到底为我们做了什么,仅仅是去除字符串两端的空格吗? 一直以为Trim()方法就是把字符串两端的空格字符给删去,其实我错了,而且错的比较离谱. 首先我直接反编译String ...
- vuex中mutation和action的详细区别
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } ...
- java中的compareto方法以及LIst列表排序的详细介绍【转】
java中的compareto方法的详细介绍 javacompareTo java中的compareto方法,返回参与比较的前后两个字符串的asc码的差值,看下面一组代码 String a=&quo ...
随机推荐
- ASP.NET MVC 5 - 开始MVC5之旅
本教程将使用Visual Studio 2013手把手教你构建一个入门的ASP.NET MVC5 Web应用程序.本教程配套的C#源码工程可通过如下网址下载:C#版本源码链接.同时,请查阅 Build ...
- 每天一个linux命令(23):Linux 目录结构
对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能,对于我们用好linux系统只管重要,下面 ...
- Java final 关键词修饰类、方法、变量
1. final修饰类 被修饰的类不能被继承,也没有子类.假如随意创建这些类的子类,子类可能会错误的修改父类的实现细节.出于安全原因,类的实现细节不允许有任何改动.在创建对象模型的时候,确信这个类不 ...
- LINQ系列:Linq to Object元素操作符
元素操作符从一个序列返回单个指定的元素. 1. DefaultIfEmpty DefaultIfEmpty操作符将一个空集合替换为包含默认的单个值的集合.在返回序列为空且又需要返回一些对象时,可以通过 ...
- floating IP 原理分析 - 每天5分钟玩转 OpenStack(107)
上一节我们通过 Web UI 创建为 cirros-vm3 分配了浮动 IP,今天将分析其工作原理. 首先查看 router 的 interface 配置: 可以看到,floating IP 已经配置 ...
- 启动第一个 KVM 虚机 - 每天5分钟玩转 OpenStack(4)
本节演示如何使用 virt-manager 启动 KVM 虚机. 首先通过命令 virt-manager 启动图形界面 # virt-manager 点上面的图标创建虚机 给虚机命名为 kvm1,这里 ...
- Javascript优化细节:短路表达式
什么是短路表达式? 短路表达式:作为"&&"和"||"操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程 ...
- Objective-C中的内存管理
在编程语言中是少不了对内存的管理的,内存对于计算机来说是宝贵的资源,所以对使用不到的资源进行回收是很有必要的.OC中使用引用计数和垃圾回收来管理内存,在OC中为每个对象分配一个引用计数器,当对象刚刚被 ...
- DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(1)
好久没写 DDD 领域驱动设计相关的文章了,嘎嘎!!! 这几天在开发一个新的项目,虽然不是基于领域驱动设计的,但我想把 DDD 架构设计的一些东西运用在上面,但发现了很多问题,这些在之前的短消息项目中 ...
- MySQL入门02-MySQL二进制版本快速部署
在上篇文章 MySQL入门01-MySQL源码安装 中,我们介绍了MySQL源码安装的方法. 源码安装虽然有着更加灵活和更加优化等诸多优势.但源码编译安装部署的过程相对复杂,而且整个过程所花费的时间很 ...