`

load方法的懒加载及原理分析

阅读更多
懒加载:

load方法与get方法的区别:
1.读取时机不同(当lazy=true的时候)
    load是采用延迟机制(load语句不读库,等使用非主键时才去读库),而get不采用延迟机制(get语句时马上读库);

2.搜索不到数据时的情况
    当搜索的数据不存在的时候,load依然会返回一个对象,在你使用该对象的非主键数据时,会抛出异常;
    当搜索的数据不存在的时候,get会返回一个null;





通过asm和cglib两个包实现;Domain是非final的。

1 session.load懒加载。

2 one-to-one(元素)懒加载:
  必须同时满足下面三个条件时才能实现懒加载(主表不能有constrained=true,所以主表没有懒加载)1)lazy!=false  2)constrainted=true  3)fetch=select

3 one-to-one(元素)懒加载:1)lazy!=false  2)fetch=select

4 many-to-many(元素):1)lazy!=false   2)fetch=select

5 many-to –many(元素):1)lazy!=false 2)fetch=select

6 懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId和getClass除外)hibernate会初始化这些代理,或用Hibernate.initialize(proxy)来初始化代理对象;当相关联的session关闭后,再访问懒加载的对象将会出现异常。


******************************************************

1.lazy是什么
    Hibernate中的lazy(默认true)网上很多人都把它叫懒人机制,主要是告诉Hibernate获取数据时在什么时候去读库;

2.lazy的影响
    就我做的例子看来。lazy只对session.Load和获取级联信息(1对1,1对多,多对多)时起作用;

3.Session读取信息的方式(Load和级联信息)
    3.1延迟加载(lazy=true)
        当我用Load或者是该bean中有级联对象的时候,执行Load的时候并不去读库,但Load还是会返回一个对象给你,但该对象中只有主键,读库是在你使用该对象的其他属性的时候去读的;
   3.2非延迟加载(lazy=false)
        在执行Load的时候就会去把库中的数据读取出来;

4.出问题的地方
    由于我们要保证Session要及时关闭,即Load完之后,我们要执行session.close操作;但是当lazy为真的时候,在Load的时候并是直接去读库,而是等使用里面属性的时候才去读库。那么到你打印信息的时候就会报session已经被关闭的错误。
    现在你是否要问,那直接把lazy设置成false不就可以了吗?现在看下面的例子吧:

5.例子(要调用Hibernate的show_sql为真)
    5.1lazy不设置,或者设置为true的时候(Load的情况)
        5.1.1代码
          
 Session session = HibernateSessionFactory.getSession();//获取session
          Tabuser tabuser = (Tabuser) session.load(Tabuser.class, new Long(1));//获取数据
            HibernateSessionFactory.closeSession();//关闭session
          System.out.println(tabuser.getUserid());
      System.out.println(tabuser.getUsername());
       
5.1.2问题
            这时会提示第5行代码出错the owning Session was closed;
            这是由于session已经被你关闭了;
        5.1.3解决
            这时的解决办法有四种:
            a)设置class标签的lazy=false;(这种方式不推荐使用)
                b)在第三行之前加入Hibernate.initialize(tabuser);
                c)使用get方法(推荐使用这个,《get和load的区别》)
                d)使用spring(网上看到的:用filter[由于spring我还不懂,现在不讲这种方式,可能这种方式会更好])
    5.2一对多映射中set标签下lazy不设置,或者设置为true的时候(获取级联信息的情况1对多)
       5.2.1代码
          
 Session session = HibernateSessionFactory.getSession();
            Tabuser tabuser = (Tabuser) session.get(Tabuser.class, new Long(1));
          HibernateSessionFactory.closeSession();
            System.out.println(tabuser.getUserid());
            System.out.println(tabuser.getUsername());
            System.out.println(tabuser.getPostlist().iterator().next().getPostid());
        5.2.2问题
           这时第6行会报错no session or session was closed;
            这是由于session已经被你关闭了;
       5.2.3解决方法有三种:
            a)set标签下设置lazy=false;(这种方式不可行)
            b)在第三行之前加入Hibernate.initialize(tabuser.getPostlist());
            c)使用spring
        5.2.4为什么说设置lazy=false不可行
            由于你在set标签后设置lazy=false的时候,那么以后你再搜索数据的时候,Hibernate都会去获取其对应的set列表(那是否浪费掉非常多的资源,设置了这个值,可能会把整个数据库中与tabuser表有级联关系的数据全读出来[一条链子])
6.总结
    大家可以运行上面的例子,并注意观察打印信息及HQL显示的位置,即可推断出HQL是什么时候执行的

7.补充
    有涉及到延迟读取好像只有Load读取和级联信息
    如果获取信息用Query的话,则执行query.list的时候就已经读库了

代码一:  此时session没有关闭,所以正常访问
	public static void main(String[] args) {
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		User user = new User("username",12356f);
		session.save(user);
		
		User user2 = (User)session.load(User.class, 1);

		System.out.println(user2.getId());		
		System.out.println(user2.getName());
		
		tx.commit();
		session.close();
		
		
	}


代码二:此时session已经关闭,出现异常


	public static void main(String[] args) {
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		User user = new User("username",12356f);
		session.save(user);
		
		User user2 = (User)session.load(User.class, 1);

		System.out.println(user2.getId());	
		
		tx.commit();
		session.close();	
		
		System.out.println(user2.getName());
	}


代码三:利用Hibernate的initial方法初始化,session关闭后也访问正常

	public static void main(String[] args) {
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		User user = new User("username",12356f);
		session.save(user);
		
		User user2 = (User)session.load(User.class, 1);
		Hibernate.initialize(user2);
		System.out.println(user2.getId());	
		
		tx.commit();
		session.close();	
		
		System.out.println(user2.getName());
	}


代码四:测试代码如上,然后修改映射文件


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.hibernate.lazy">

	<class name="User" table="user" lazy="false">
		<id name="id" unsaved-value="-1">
			<generator class="native" />
		</id>
		<property name="name" />
		<property name="wage"/>
		
	</class>
</hibernate-mapping>


注意:lazy="false">

此时访问及时session关闭,那也会正常
分享到:
评论

相关推荐

    jquery lazyload延迟加载技术的实现原理分析

    懒加载技术(简称lazyload)并不是新技术,它是js程序员对网页性能优化的一种方案。lazyload的核心是按需加载。在大型网站中都有lazyload的身影,例如谷歌的图片搜索页,迅雷首页,淘宝网,QQ空间等。因此掌握lazyload...

    PHP 自动加载类原理与用法实例分析

    本文实例讲述了PHP 自动加载类原理与用法。分享给大家供大家参考,具体如下: 类的自动加载 (Autoloading Classes) 在编写面向对象(OOP) 程序时,很多开发者为每个类新建一个 PHP 文件。 这会带来一个烦恼:每个...

    VB6.0动态加载ActiveX控件漫谈

    显然利用该方法不行,通过分析VBControls等相关对象,找出VBControlExtender对象 与EventInfo相结合能提供事件陷井捕捉,VBControlExtender对象对动态添加控件特 别有用,它提供了一套通用的属性、方法、事件给开发...

    异步并行加载工具Asyncload.zip

    最终的出路只能异步 并行,从而诞生了该开源产品项目介绍名称:asyncload译意: async cocurrent load语言: 纯java开发定位: 业务层异步并行加载工具包,减少页面响应时间工作原理原理描述:针对方法调用,...

    深入分析Android加载so文件

    Android系统中使用ndk进行编程,有很多的好处(Java的跨平台特性导致其本地交互的能力不够强大,一些和操作系统相关的特性Java无法完成;代码的保护:由于apk的java层代码很容易被反编译,而...System.loadLibraray(Str

    QQ怎么运行起来的?CPU、内存、硬盘和主板的关系

    所以,不管是运行QQ还是编辑Word文档,都是先将硬盘上的数据复制到内存,才能让CPU来处理,这个过程就叫作载入内存(Load into Memory)。完成这个过程需要一个特殊的程序(软件),这个程序就叫做加载器(Loader)。 CPU...

    jQuery权威指南366页完整版pdf和源码打包

    3.10.3 功能实现 3.10.4 代码分析 3.11 本章小结 第4章 jquery中的事件与应用 4.1 事件机制 4.2 页面载入事件 4.2.1 ready()方法的工作原理 4.2.2 ready()方法的几种相同写法 4.3 绑定事件 ...

    Linux内核完全公平调度器的分析及模拟.pdf

    "Linux内核完全公平调度器的分析及模拟" 一、引言 操作系统内核调度算法历来是人们改进系统性能的研究热点。作为主流操作系统之一的Linux,它的调度算法几经改进,表现出优异的性能,在越来越多的领域逐渐占据重要...

    jQuery权威指南-源代码

    4.2.1 ready()方法的工作原理/85 4.2.2 ready()方法的几种相同写法/86 4.3 绑定事件/86 4.4 切换事件/90 4.4.1 hover()方法/90 4.4.2 toggle()方法/93 4.5 移除事件/94 4.6 其他事件/96 4.6.1 方法one() /...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    Webview window in android used to load pages just works like browser, as well as there is only one webview running at the same time. (2)Cross-domain data interaction. Different webviews can not share...

    buaa eda的作业

    该模块的输入信号包括时钟信号clk、复位信号reset、使能信号en、加载信号load和数据输入信号d。输出信号包括计数输出co、缓冲信号qh和ql、时钟输出adclk和daclk。 行注释 在该VHDL代码中,行注释量大量使用,行...

    32位嵌入式处理器S698的SPARC V8指令集.pdf

    "32位嵌入式处理器S698的SPARC V8指令集.pdf" ...本文对SPARC V8指令集的特点、寻址方式、基本操作指令和指令格式进行了详细的分析,旨在帮助读者更好地理解SPARC V8指令集的工作原理和应用场景。

    数据预处理实训(kettle预处理+可视化大屏展示)-kettle和datax比较

    将光碟租赁店存放在MySQL数据库(sakila)中的记录整个租赁行为以及表征租赁内容的数据加载到数据仓库(sakila_dwh)中,然后再对数据仓库中的数据使用任意一种可视化开发方式(如JavaWeb/Django/Flask+ECharts)做...

    J2EE应用开发详解

    29 3.2.2 Class.forName()加载类的实例 30 3.2.3 loadClass获得类的实例 31 3.3 操作类的字段 31 3.3.1 获取对象的属性 31 3.4 操作类的方法 34 3.4.1 运行时调用对象的方法 34 3.4.2 无参构造函数 36 3.4.3 带参...

    asp.net知识库

    使用.ashx文件处理IHttpHandler实现发送文本及二进制数据的方法 制作一个简单的多页Tab功能 一完美的关于请求的目录不存在而需要url重写的解决方案! 在C#中实现MSN消息框的功能 XmlHttp实现无刷新三联动ListBox 鼠标...

    汪文君高并发编程实战视频资源全集

     高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4  高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4  高并发编程第三阶段13讲 一个JNI程序的编写,通过...

    汪文君高并发编程实战视频资源下载.txt

     高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4  高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4  高并发编程第三阶段13讲 一个JNI程序的编写,通过...

    java图书馆里系统源码-YangtzeuApp:新长大助手项目,长江大学教务处

    java图书馆里系统源码 新长大助手 应用简介 ...图片加载框架,链式调用,一行代码加载网络图片,支持gif,很方便 Glide.with(context).load(iamge).into(imageView); 4. 官方的json数据解析框架,很方便

    基于单片机的定时蜂鸣器课程设计报告.doc

    " "方案设计 "35 "方案选择合理,分析、设计正确,原理清 " " " " "楚,电路、程序流程图清晰,结构合理, " " " " "程序简洁、正确。 " " "调试 "15 "过程清晰,调试方案设计合理,测试点选 " " " " "择适当,程序...

Global site tag (gtag.js) - Google Analytics