Hibernate延迟加载原理与实现方法

 更新时间:2016年03月24日 14:05:37   作者:张国亮  
这篇文章主要介绍了Hibernate延迟加载原理与实现方法,较为详细的分析了Hibernate延迟加载的概念,原理与相关实现技巧,需要的朋友可以参考下

本文实例讲述了Hibernate延迟加载原理与实现方法。分享给大家供大家参考,具体如下:

为了进一步优化Hibernate的性能,可以使用:

延迟加载技术、管理数据抓取策略、进行缓存管理 等方面考虑来提高Hibernate的性能。

1. 延迟加载(load)

延迟加载(load)是Hibernate为提高程序执行效率而提供的一种机制,即只有真正使用该对象的数据时才会创建

延迟加载的过程:通过代理(Proxy)机制来实现延迟加载。Hibernate从数据库获取某一个对象数据时、获取某一个对象的集合属性值时,或获取某一个对象所关联的另一个对象时,由于没有使用该对象的数据(除标识符外),Hibernate并不从数据库加载真正的数据,而只是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都为默认值;只有在真正需要使用该对象的数据时才创建这个真正的对象,真正从数据库中加载它的数据

当调用Session上的load()方法加载一个实体时;当Session加载某个实体时,会对这个实体中的集合属性值采用延迟加载;当Session加载某个实体时,会对这个实体所单端关联的另一个实体对象采用延迟加载

关闭延迟加载:在加载单个实体时,可以使用get()方法

对于实体中的集合属性,可以在这个集合的(<set>,<bag>,<list>…)添加属性lazy="false"。单端关联另一个实体对象时,可以在映射文件中配置<one-to-one>,<many-to-one> 添加属性lazy="false"注意:one-to-one不能有constrained=true(产生的sql语句中显示外键),否则懒加载不起作用。

2. Hibernate中默认采用延迟加载的情况主要有以下几种:

• 当调用Session上的load()方法加载一个实体时会采用延迟加载。
• 当Session加载某个实体时,会对这个实体中的集合属性值采用延迟加载。(one-to-many)
• 当Session加载某个实体时,会对这个实体所单端关联(one-to-one, many-to-one)的另一个实体对象采用延迟加载。
• 第二种和第三种的区别是:第二种情况下取消延时加载的方法是在单方即有set属性的一方的映射文件的set标签后设置懒加载的属性lazy="false";第三种情况则是在多方即有many-to-one的一方的映射文件中的many-to-one标签后设置lazy="false"。

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

3. 抓取策略(fetch)

通过配置"抓取策略"来直接影响session的get()和load()方法的查询效果。

单端关联<many-to-one><one-to_one>上的抓取策略:

可以给单端关联的映射元素添加fetch属性。select:延迟加载; join:在同一条select语句使用内连接来获得对象的数据和它关联对象的数据,此时关联对象的延迟加载失效。

集合属性上的抓取策略:

select:延迟加载;join:在同一条select语句使用内连接来获得对方的关联集合。此时关联集合上的lazy会失效。subselect:另外发送一条查询语句或子查询抓取。这个策略对HQL的查询也起作用。

4. 延迟加载案例分析

情况一:单个实体调用load()方法取消懒加载

package com.hbsi.test;
import org.hibernate.Session;
import org.junit.Test;
import com.hbsi.domain.User;
import com.hbsi.utils.HibernateUtil;
publicclass TestLazy {
//测试get()方法;get()方法不管你有没有用到,总会执行sql语句
@Test
publicvoid testGet(){
Session session = HibernateUtil.getSession();
User user = (User) session.get(User.class,1);
// System.out.println(user.getName());
HibernateUtil.close();
//这里要注意的是:即使关闭了session,使user处于托管状态,仍然可以可以使用user对象;这是因为虽然处于托管状态,但是这个对象是存在属性值的对象,并没有把他删除,只是隔绝了它与数据库的打交道的通道。
System.out.println(user.getName());
}
//测试load()方法;不执行sql语句,用到的时候才执行
@Test
publicvoid testLoad(){
Session session = HibernateUtil.getSession();
User user = (User) session.load(User.class,1);
//这里输出id也不会执行sql语句,直接从上面你传进去的id中获取id,没有从数据库中查找,所以也不执行sql语句
System.out.println(user.getId());
//而输出name就不一样了,这时其实就是实例化了代理对象,这是的代理对象有了name的属性,这时即使你关闭了session,也可以通过这个对象获取到name;如果注释这句,即不实例化代理对象,又在关闭session后执行输出name属性,这时会报错:could not initialize proxy
// System.out.println(user.getName());
HibernateUtil.close();
System.out.println(user.getName());
}
}

情况二:set集合上取消懒加载

测试如果在映射文件中将集合属性中的懒加载设置为false后将连带着orders表中数据一块提出来,即两条select语句

@Test
publicvoid find(){
Session session = HibernateUtil.getSession();
Customer cus = (Customer) session.get(Customer.class,3);
System.out.println(cus.getCname());
//用到下面这种方法输出会出现两天sql语句,而且是分开的;如果用到懒加载会出现先输出两条sql语句,在输出结果
//这里不能直接方法链式输出cus.getOrd().getOname();因为cus.getOrd()返回的是一个set集合
Set<Orders> orders = cus.getOrd();
System.err.println(orders.size());
HibernateUtil.close();
}

方法三:<one-to-one>,<many-to-one> 取消懒加载

@Test
publicvoid find(){
//默认使用懒加载,即用着一条sql语句就输出一条;如果设置延时加载为false后输出两条sql语句,将不需要的顾客信息也查出来
Session session = HibernateUtil.getSession();
Orders ord = (Orders) session.get(Orders.class,3);
System.out.println(ord.getOname());
HibernateUtil.close();
}

希望本文所述对大家基于Hibernate框架的Java程序设计有所帮助。

相关文章

  • 详解Java的位操作符

    详解Java的位操作符

    位操作就是对这些数据进行基本的操作。如果基本类型是char、byte或者short类型的数值进行移位处理,那么会转化成int类型,再进行移位的处理
    2017-09-09
  • 通过xml配置SpringMVC注解DispatcherServlet初始化过程解析

    通过xml配置SpringMVC注解DispatcherServlet初始化过程解析

    这篇文章主要为大家介绍了通过xml配置SpringMVC注解DispatcherServlet初始化过程解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Java异步编程工具Twitter Future详解

    Java异步编程工具Twitter Future详解

    这篇文章主要介绍了Java异步编程工具Twitter Future详解,包括基本用法示例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • idea如何通过maven指定JDK版本

    idea如何通过maven指定JDK版本

    这篇文章主要介绍了idea如何通过maven指定JDK版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java高性能新一代构建工具Maven-mvnd(实践可行版)

    Java高性能新一代构建工具Maven-mvnd(实践可行版)

    这篇文章主要介绍了Java高性能新一代构建工具Maven-mvnd(实践可行版),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • 使用Java自带的mail API实现邮件发送功能全过程

    使用Java自带的mail API实现邮件发送功能全过程

    电子邮件的应用非常广泛,例如在某网站注册了一个账户,自动发送一封欢迎邮件,通过邮件找回密码,自动批量发送活动信息等,下面这篇文章主要给大家介绍了关于如何使用Java自带的mail API实现邮件发送功能的相关资料,需要的朋友可以参考下
    2023-04-04
  • SpringMVC请求参数的使用总结

    SpringMVC请求参数的使用总结

    在日常使用SpringMVC进行开发的时候,有可能遇到前端各种类型的请求参数,本文主要接介绍了SpringMVC请求参数的使用总结,感兴趣的可以了解一下
    2021-06-06
  • SpringBoot自动装配原理详解

    SpringBoot自动装配原理详解

    这篇文章主要介绍了SpringBoot自动装配原理的相关资料,帮助大家更好的理解和学习使用SpringBoot框架,感兴趣的朋友可以了解下
    2021-03-03
  • java 中线程等待与通知的实现

    java 中线程等待与通知的实现

    这篇文章主要介绍了java 中线程等待与通知的实现的相关资料,希望通过本文能帮助到大家,让大家掌握这样的功能,需要的朋友可以参考下
    2017-09-09
  • Java OpenCV学习之Mat的基本操作详解

    Java OpenCV学习之Mat的基本操作详解

    OpenCV用来存储图像,很多时候都会用到这个Mat方法。数字图像可看做一个数值矩阵, 其中的每一个元素表明一个像素点。Mat在 OpenCV 中表示的是 N 维稠密矩阵,与稠密矩阵相对的是稀疏矩阵。本文将重点介绍OpenCV中Mat的一些基本操作,需要的可以参考一下
    2022-03-03

最新评论