Hibernate延迟加载机制

Hibernate延迟加载机制深度解析 延迟加载(Lazy Loading)是Hibernate的一种性能优化策略,它推迟对象关联数据的加载时机,只有在真正访问这些关联数据时才会从数据库加载。这种机制有效减少了不必要的数据库查询,显著提升了应用性能。默认使用LAZY:除明确需要立即加载的关联外,全部配置为延迟加载合理使用JOIN FETCH:对确实需要立即加载的关联使用关注Session生命周期:确保在Session打开时访问延迟属性监控查询数量:定期检查是否产生N+1问题考虑DTO投影:复杂查询使用专用DTO代替实体测试不同场景。 阅读详情
所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以提高程序的性能。

延迟加载一般有三种类型:

1. 实体对象的延迟加载:

在×.hbm.xml文件中的配置如下:

<hibernate-mapping>
<class name=”com.neusoft.entity.User” table=”user” lazy=”true”>
    ……
</class>
</hibernate-mapping>

通过将class的lazy属性设置为true,来开启延迟加载特性。

调用代码如下:

User user=(User)session.load(User.class,”1”);(1)
System.out.println(user.getName());(2)

当程序运行到(1)的时候,Hibernate并没有查询相应的数据,只有当程序执行到(2)的时候,hibernate才会发起数据库查询操作。
hibernate是通过中间代理对象来实现延迟加载的,因为session.load() 返回的是一个实体对象的代理类,这里所返回的就是User对象的代理类。代理类中包含目标对象的所有属性和方法,并且属性值被赋值为空,当执行getname() 方法的时候,实际上是通过调用代理对象的getname方法来得到值,然后代理对象再去查询数据库。
2. 集合类型的延迟加载

。hbm。xml的配置如下;

<hibernate-mapping>
    <class name=”com.neusoft.entity.User” table=”user”>
…..
<set name=”addresses” table=”address” lazy=”true” inverse=”true”>
<key column=”user_id”/>
<one-to-many class=”com.neusoft.entity.Arrderss”/>
</set>
    </class>
</hibernate-mapping>

通过将<set>元素的lazy属性设置为true来开启集合类型的延迟加载特性。我们看下面的代码:

User user=(User)session.load(User.class,”1”);
Collection addset=user.getAddresses();       (1)
Iterator it=addset.iterator();                (2)
while(it.hasNext()){
Address address=(Address)it.next();
System.out.println(address.getAddress());
}

当程序执行到(1)处时,这时并不会发起对关联数据的查询来加载关联数据,只有运行到(2)处时,真正的数据读取操作才会开始,这时Hibernate会根据缓存中符合条件的数据索引,来查找符合条件的实体对象。
在Hibernate中对集合类型进行缓存时,是分两部分进行缓存的,首先缓存集合中所有实体的id列表,然后缓存实体对象,这些实体对象的id列表,就是所谓的数据索引。当查找数据索引时,如果没有找到对应的数据索引,这时就会一条select SQL的执行,获得符合条件的数据,并构造实体对象集合和数据索引,然后返回实体对象的集合,并且将实体对象和数据索引纳入Hibernate的缓存之中。另一方面,如果找到对应的数据索引,则从数据索引中取出id列表,然后根据id在缓存中查找对应的实体,如果找到就从缓存中返回,如果没有找到,在发起select SQL查询。在这里我们看出了另外一个问题,这个问题可能会对性能产生影响,这就是集合类型的缓存策略。如果我们如下配置集合类型:

<hibernate-mapping>
    <class name=”com.neusoft.entity.User” table=”user”>
…..
<set name=”addresses” table=”address” lazy=”true” inverse=”true”>
<cache usage=”read-only”/>
<key column=”user_id”/>
<one-to-many class=”com.neusoft.entity.Arrderss”/>
</set>
    </class>
</hibernate-mapping>

这里我们应用了<cache usage=”read-only”/>配置,如果采用这种策略来配置集合类型,Hibernate将只会对数据索引进行缓存,而不会对集合中的实体对象进行缓存。如上配置我们运行下面的代码:

User user=(User)session.load(User.class,”1”);
Collection addset=user.getAddresses();      
Iterator it=addset.iterator();               
while(it.hasNext()){
Address address=(Address)it.next();
System.out.println(address.getAddress());
}
System.out.println(“Second query……”);
User user2=(User)session.load(User.class,”1”);
Collection it2=user2.getAddresses();
while(it2.hasNext()){
Address address2=(Address)it2.next();
System.out.println(address2.getAddress());
}

运行这段代码,会得到类似下面的输出:
Select * from user where id=’1’;
Select * from address where user_id=’1’;
Tianjin
Dalian
Second query……
Select * from address where id=’1’;
Select * from address where id=’2’;
Tianjin
Dalian

我们看到,当第二次执行查询时,执行了两条对address表的查询操作,为什么会这样?这是因为当第一次加载实体后,根据集合类型缓存策略的配置,只对集合数据索引进行了缓存,而并没有对集合中的实体对象进行缓存,所以在第二次再次加载实体时,Hibernate找到了对应实体的数据索引,但是根据数据索引,却无法在缓存中找到对应的实体,所以Hibernate根据找到的数据索引发起了两条select SQL的查询操作,这里造成了对性能的浪费,怎样才能避免这种情况呢?我们必须对集合类型中的实体也指定缓存策略,所以我们要如下对集合类型进行配置:

<hibernate-mapping>
    <class name=”com.neusoft.entity.User” table=”user”>
…..
<set name=”addresses” table=”address” lazy=”true” inverse=”true”>
<cache usage=”read-write”/>
<key column=”user_id”/>
<one-to-many class=”com.neusoft.entity.Arrderss”/>
</set>
    </class>
</hibernate-mapping>
此时Hibernate会对集合类型中的实体也进行缓存,如果根据这个配置再次运行上面的代码,将会得到类似如下的输出:
Select * from user where id=’1’;
Select * from address where user_id=’1’;
Tianjin
Dalian
Second query……
Tianjin
Dalian
这时将不会再有根据数据索引进行查询的SQL语句,因为此时可以直接从缓存中获得集合类型中存放的实体对象。
3. 属性的延迟加载

如下配置我们的实体类:



<hibernate-mapping>

<class name=”com.neusoft.entity.User” table=”user”>

……

<property name=”resume” type=”java.sql.Clob” column=”resume” lazy=”true”/>

    </class>

</hibernate-mapping>

通过对<property>元素的lazy属性设置true来开启属性的延迟加载,

根据上面的配置,执行代码如下:

String sql=”from User user where user.name=’zx’ ”;

Query query=session.createQuery(sql);    (1)

List list=query.list();

for(int i=0;i<list.size();i++){

User user=(User)list.get(i);

System.out.println(user.getName());

System.out.println(user.getResume());    (2)

}



当执行到(1)处时,会生成类似如下的SQL语句:



Select id,age,name from user where name=’zx’;



这时Hibernate会检索User实体中所有非延迟加载属性对应的字段数据,当执行到(2)处时,会生成类似如下的SQL语句:



Select resume from user where id=’1’;



这时会发起对resume字段数据真正的读取操作。
【C++解题报告】求最大公约数问题(辗转相除法) 题目来源:     基础班《函数、递推、递归》,递归第5题。     北大OJ-NOI 2.2基本算法之递归和自调用函数  7592 描述:          总时间限制:1000ms  内存限制:65536KB      给定两个正整数,求它们的最大公约数。 输入:       输入一行,包含两个正整数( 输出:        输出一 阅读详情

相关推荐

C++备忘录035:求相邻最小值的几种方式

auto foo1() -> int { std::array<int, a.size()> b; std::adjacent_difference(cbegin(a), cend(a), begin(b)); return *std::min_element(std::next(cbegin(b)), cend(b)); } auto foo2() -...

u011241498的博客 742

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

主要介绍了Hibernate延迟加载原理与实现方法,较为详细的分析了Hibernate延迟加载的概念,原理与相关实现技巧,需要的朋友可以参考下

hibernate属性延时加载如何操作、相应的jar包

hibernate3的属性延时加载是个很有意义的东西,它能让你把你不想加载到内存里的东西在查询的时候排除。 我相信来下载这个东西的人都已经很了解这一块的知识了,只是配不对那个类增强器才来下载我这个文件。 这些资料是我刚刚做完的一个测试后整理出来的,那四个jar包是我运行出错后,找了好久才找到的能用的版本,相信对你有用。

Hibernate 延迟加载

使⽤延迟加载可以提⾼程序的运⾏效率,Java 程序与数据库交互的频次越低,程序运⾏的效率就越⾼, 所以我们应该尽量减少 Java 程序与数据库的交互次数,Hibernate 延迟加载就很好的做到了这⼀点。客户和订单,当我们查询客户对象时,因为有级联设置,所以会将对应的订单信息⼀并查询出来,这样 就需要发送两条 SQL 语句,分别查询客户信息和订单信息。延迟加载的思路是:当我们查询客户的时候,如果没有访问订单数据,只发送⼀条 SQL 语句查询客户信 息,如果需要访问订单数据,则发送两条 SQLL。

weixin_57558097的博客 716

Hibernate延迟加载及关联关系的查询策略

【版权所有,文章允许转载,但须以链接方式注明源地址,否则追究法律责任】 为什么hibernate需要延迟加载? 通过关联关系可以在程序中方便地获取关联对象的数据,但是如果从数据库中加载Student对象时,就同时自动加载所有关联的Grade对象,而程序实际上仅仅需要访问Student对象时,那么这些关联的Grade对象就白白浪费了许多内存空间。Hibernate查询Student对象时,立即查...

q_1092535160的博客 449

Hibernate(18)Hibernate延迟加载是什么?

Hibernate延迟加载(Lazy Loading)是一种性能优化技术,仅在需要时加载关联数据,减少初始查询和内存消耗。本文通过完整示例演示了延迟加载的实现方式,包括: 配置hibernate.cfg.xml文件 创建HibernateUtil工具类 定义Student和Course实体类,使用@OneToMany和@ManyToOne注解设置延迟加载策略 示例代码展示如何在实际操作中处理延迟加载的数据 关键点:通过fetch = FetchType.LAZY设置延迟加载策略,在会话关闭前访问关联数据以避

qq_43012298的博客 457

Hibernate之lazy延迟加载

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34138139的博客 252

c++-用c++解决简单数学问题

这段代码演示了如何用C++语言解决几个简单的数学问题,包括求平方根、绝对值、最大值、最小值和幂运算。通过调用C++的内置函数,可以很方便地解决这些问题。将需要计算的数值传入相应的函数,然后输出结果即可。

万物复苏101的博客 518

C++第一次上机实验报告—02

一、问题及代码/* * 文件名称:three word.cpp * 作 者:王聪 * 完成日期:2016年3月10日 * 版 本 号:v1.0 * 输入描述:输入a,b,c三个不同的数 * 问题描述:求a,b,c三个数的最大值 * 程序输出:输出a,b,c三个数的最大值 * 问题分析:略 * 算法设计:略 */ #include using namespace

blog_tanlang的博客 420

C++求1-100的质数编程

今天在baidu知道里面看到有位兄弟在问c++不用函数求质数的问题,其实我也不知道有没有函数直接求质数的,反正也是闲着,而且也好久没有用过(大学用过),就尝试写写吧~ 谁知道一开始写就有很多的关键字忘了,而且写了好都输出空的字符,实在是头疼呀,只能用visual c的debug一步一步来看参数的变化,最后才修改好~不过也很累赘,发出来跟朋友交流交流,希望能改到最简的代码.#inc

boyzone的专栏 8270

求最大数(题目来源:JLOJ2331)

求最大数 Description 由键盘输入任意 3 个整数 x,y,z,求这 3 个数中的最大数并输出。 Input 输入 3 个整数。 Output 最大数。 Sample Input 2 8 -6 Sample Output 8 解题思路: 先定义一个变量 max ,将输入的第一个值赋值给变量 max ,然后将剩下的两个值依次与 max 作比较,将较大的值赋给 max 。 参考代码: #include <stdio.h> int main() { int a, b, c, max;

英雄爱吃土豆片的博客 346

hibernate延迟加载解决

hibernate延迟加载解决

第四周实践项目1————求最大公约数

/*copyright(c)2016.烟台大学计算机学院 * All rights reserved, * 文件名称:text.Cpp * 作者:吴敬超 * 完成日期:2016年3月22日 * 版本号:vc++6.0 * * 问题描述: 输入两个数,求最大公约数 * 输入描述: 输入两个数 * 程序输出: 最大公约数 */ #include using

jnwujingchao的博客 431

C++算法之巧解数学问题

巧解数学问题 利用C++求解经典数学问题 1.公倍数与公因数 利用辗转相除法,我们可以很方便地求得两个数的最大公因数(greatest common divisor,gcd);将两个数相乘再除以最大公因数即可得到最小公倍数(least common multiple, lcm)。 首先介绍一下辗转相除法: #include<iostream> #include<cstdio> using namesapce std; int fun(int m,int n) { int r

yohnyang的博客 2005

信息学奥赛一本通 1207:求最大公约数问题 递归算法

时间限制: 1000 ms 内存限制: 65536 KB。输入一行,包含两个正整数(

长春高老师编程 1075

利用自定义函数,求两数最大公约数

/* * 程序的版权和版本声明部分 * Copyright (c)2013, 烟台大学计算机学院 * All rightsreserved. * 文件名称:xx.cpp * 作 者:赵加响 * 完成日期:2013年11月5日 * 版 本 号: v1.0 * 输入描述:两个正整数 * 问题描述:利用自定义函数,求两数最大公约数 * 程序输出:两数最大公约数 * 问题分析:

u012369106的专栏 3019

我的C++程序

/* * 文件名称:myproject3 * 作 者: 石宇建 * 完成日期: 2016 年 3 月 10 日 * 版 本 号:v1.0 * 对任务及求解方法的描述部分:求圆的面积 * 输入描述:我的第三个C++程序 * 问题描述:无 * 程序输出:无 * 问题分析:略 * 算法设计:略 */ #include using namespace st

syj0105的博客 360

《算法笔记》2.5小节——C/C++快速入门->数组 问题 J: 例题6-9 字符串求最大值

问题 J: 例题6-9 字符串求最大值题目描述输入输出样例输入样例输出示例代码 题目描述 从键盘上输入3个字符串,求出其中最大者。 输入 输入3行,每行均为一个字符串。 输出 一行,输入三个字符串中最大者。 样例输入 England China America 样例输出 England 示例代码 #include<iostream> #include<string.h> using namespace std; int main(){ char str1[10]; cha

有出路CodingTime 146
上一篇: Hibernate中session的用法
下一篇: Open Session In View探讨
chenwc_csu
博客等级 码龄20年 1粉丝 6原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值