`

第十三章 lazy懒加载

阅读更多
lazy属性:懒加载
作用:当调用方法的时候才去执行要执行的SQL语句.
我们以班级学生为示例:
请看班级的配置文件MyClass.hbm.xml
<hibernate-mapping>
<class name="chapter9.model.MyClass" table="myclass">
<id name="id" type="java.lang.String" column="id" length="32">
<generator class="uuid.hex" />
</id>
<property name="name" type="java.lang.String" column="name"
length="20" />
<set name="students">
<key column="student_id" />
<one-to-many class="chapter9.model.Student" />
</set>
</class>
</hibernate-mapping>

重点要看这里<set name="students">,班级对象持久一个学生集合,我们用以下测试代码:
public class Test {
public static void main(String[] args) throws Exception {
MyClassDao myClassDao = new MyClassDao();
StudentDao studentDao = new StudentDao();

MyClass myClass = myClassDao.findById("4028810027d8be080127d8be0d6a0001");
Thread.sleep(5000);
Set<Student> students = myClass.getStudents();
for(Student s:students){
System.out.println(s.getName());
}
}
}
Thread.sleep(5000);是让程序暂停5秒钟,
当我们执行程序以后,可以看到出错了:




但是我们看到程序执行了一条查询语句
select myclass0_.id as id0_0_, myclass0_.name as name0_0_ from myclass myclass0_ where myclass0_.id=?

这一条查询语句对应的是
MyClass myClass = myClassDao.findById("4028810027d8be080127d8be0d6a0001");

可以看到程序正常执行的默认行为是:
当你执行到Set<Student> students = myClass.getStudents();这一句时,也就是当你调用getStudents();方法时,程序才会去再一次查询数据库取出学生集合,但是当程序去数据库查询取学生信息的时候,却发现hibernate关闭了session,所以报了一个错误:
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: chapter1.model.MyClass.students, no session or session was closed
no session or session was closed意思是指session对象已经关闭了.

那么怎么解决这个问题呢?
这个问题一直是使用Hibernate的一个缺陷,一直到现在都没有一个很好的解决方案.后面在Spring中会有一个OpenSessionInView解决方案.但也会有很多缺陷.

暂时的解决方案,
 不懒加载
我们只需要给set标签添加一个属性即可.
<set name="students" lazy="false">
<key>
<column name="student_id" length="32" />
</key>
<one-to-many class="chapter1.model.Student" />
</set>
lazy="false"的意思是取消懒加载的行为,那么我们再执行一下刚才的代码,可以看到以下结果:




程序是执行成功了,但是当执行myClassDao.findById("4028810027d8be080127d8be0d6a0001");这一句代码的时候,可以看到程序执行了两条查询语句,程序已经将关联的学生集合取出来了,这就违背了我们的初衷.

 解决方案二:传参数决定是否懒加载
解决懒加载的问题要记住一条,就是要把有用的数据在session关闭之前将数据取出来.
配置文件改为:
<set name="students" lazy="true">
<key>
<column name="student_id" length="32" />
</key>
<one-to-many class="chapter1.model.Student" />
</set>
lazy="true"指定了当程序调用方法时才去执行SQL语句取值,
修改Dao层
transaction.begin();
myClass = (MyClass) session.get(MyClass.class, id);
myClass.getStudents();
transaction.commit();
可以看到myClass.getStudents();这句代码,感觉有点奇怪,就只是调用了一下获取学生集合的方法,但是当你调用这个方法的时候,学生数据就被取出来了.不过这样的写法会产生二异性,就这么放在那里,如果换了其他人看你的代码,可能不知道作用是什么,可能后面维护你代码的人就将这句代码注释掉了,但是一注释就会出问题了,学生集合取不出来了.

Hibernate类提供了一个静态方法来修饰这个作用,将代码改为下面:
transaction.begin();
myClass = (MyClass) session.get(MyClass.class, id);
Hibernate.initialize(myClass.getStudents());
transaction.commit();
这样写了以后,后面维护你代码的人就能够看懂这句话的作用了.

但是现在还是和lazy="false"时的作用一样,如果我后面不需要用到学生集合怎么办,因为这个时候不管你用不用,学生集合都被取出来了.

那如果我现在有时候想取出学生集合,有时候又不想取出学生集合怎么办呢,不可能硬性的将lazy="false",如果这样,就有点不合理了,我们可以给方法加一个boolean值的参数,来决定是否取出学生集合.
将Dao层改为:
public MyClass findById(Serializable id, boolean isLazy) throws Exception {
Session session = null;
Transaction transaction = null;
MyClass myClass = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
myClass = (MyClass) session.get(MyClass.class, id);
if(isLazy){
Hibernate.initialize(myClass.getStudents());
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return myClass;
}
这个时候我们就可以控制是否懒加载了,需要学生集合就取,不需要就不取.非常灵活,但是给方法增加了一点复杂度.记住这时lazy="true"

那么在main方法中调用时就得多传一个参数了.
MyClass myClass = myClassDao.findById(
"4028810027d8be080127d8be0d6a0001", true);

  • 大小: 9.4 KB
  • 大小: 33 KB
分享到:
评论

相关推荐

    rust-lazy-foo:遵循使用Rust的Lazy Foo SDL2示例

    Lazy Foo的SDL2教程,在Rust中 此库使用以下真棒人员提供的Rust包装器,将教程的端口包含到编程语言中: SDL2: 这些示例至少假定为0.27.2。 注意:从rust-sdl2 0.27.2开始,这两个库...第13课-Alpha混合 第14课-动画

    NHibernate中文文档

    延迟初始化(延迟加载)(Lazy Initialization) 14 集合排序(Sorted Collections) 14 使用 &lt;idbag&gt; 14 双向关联(Bidirectional Associations) 14 三重关联(Ternary Associations) 15 异类关联(Heterogeneous ...

    深入解析Windows操作系统中文.part2.rar

    第13章 网络 787 13.1 Windows的网络总体结构 787 OSI参考模型 787 Windows网络组件 789 13.2 网络API 791 Windows套接字(Windows Sockets) 791 远过程调用 798 Web访问API 803 命名管道和邮件槽 804 NetBIOS 811 ...

    WordPress主题:XIU主题 v7.5

    图片和头像提速:文章列表和头像都使用了lazyload做按需异步加载,你会发现访问速度上提升一大截 2种可选框架:支持3栏和2栏 13种可选颜色风格:基本上小清新的颜色都有了 3种列表模式:多图展示、单图展示、无图展示 7...

    UNIX 高级教程系统技术内幕

    第13 章 虚存(352) 13.1 简介 13.1.1 内存管理的石器时代 13.2 分页 13.2.1 功能需求 13.2.2 虚拟地址空间 13.2.3 页面初始访问 13.2.4 交换区 13.2.5 转换映射图 13.2.6 页面替换策略 13.3 硬件需求 13.3.1 MMU ...

    WordPress阿里百秀XIU v7.5博客主题 完美无限制.zip

     置顶焦点图:绝美展示,可自行设置置顶文章,且第一章大图可自定义  近期热门排行榜:最近多少天的评论热门文章排行,可设置天数和显示数量  独立页面:点赞最多的文章排行  导航多级菜单:不管你听不听,我是建议...

    CLR via C# 3rd Edition

    第三版的目录及新增内容如下: Part I – CLR Basics Chapter 1-The CLR’s Execution Model 增加了/optimize和/debug的讨论,及其相互关系。 Chapter 2-Building, Packaging, Deploying, and Administering ...

    WordPress主题:XIU主题 v5.6.zip

    置顶焦点图:绝美展示,可自行设置置顶文章,且第一章大图可自定义 近期热门排行榜:最近多少天的评论热门文章排行,可设置天数和显示数量 独立页面:点赞最多的文章排行 导航多级菜单:不管你听不听,我是建议你...

    阿里百秀 XIU v7.0 秀主题下载2019最新版

    图片和头像提速:文章列表和头像都使用了lazyload做按需异步加载,你会发现访问速度上提升一大截 2种可选框架:支持3栏和2栏 13种可选颜色风格:基本上小清新的颜色都有了 3种列表模式:多图展示、单图展示、无图展示 7...

    阿里百秀XIU主题v7.5全解密博客主题 完美无限制 WordPress主题模板

    置顶焦点图:绝美展示,可自行设置置顶文章,且第一章大图可自定义 近期热门排行榜:最近多少天的评论热门文章排行,可设置天数和显示数量 独立页面:点赞最多的文章排行 导航多级菜单:不管你听不听,我是建议你最多二...

    Java学习笔记-个人整理的

    {13}JDBC}{191}{chapter.13} {13.1}forName}{191}{section.13.1} {13.2}JDBC}{191}{section.13.2} {13.3}连接Oracle数据库及操作}{192}{section.13.3} {13.4}批处理模式}{195}{section.13.4} {13.5}分页查询}{...

    WordPress主题 大前端 阿里百秀 XIU ALIBAIXIU 小清新CMS高级主题[更新v3.2]

    图片和头像提速:文章列表和头像都使用了lazyload做按需异步加载,你会发现访问速度上提升一大截 2种可选框架:支持3栏和2栏 13种可选颜色风格:基本上小清新的颜色都有了 3种列表模式:多图展示、单图展示、无图展示 7...

    阿里百秀XIU v7.5兼容wordpress5.4+ 全解密博客文章主题源码 完美无限制

    图片和头像提速:文章列表和头像都使用了lazyload做按需异步加载,你会发现访问速度上提升一大截 2种可选框架:支持3栏和2栏 13种可选颜色风格:基本上小清新的颜色都有了 3种列表模式:多图展示、单图展示、无图展示 7...

    Wordpress 博客主题/模板 阿里百秀XIU主题 2.1最新版CMS高级主题

    图片和头像提速:文章列表和头像都使用了lazyload做按需异步加载,你会发现访问速度上提升一大截 2种可选框架:支持3栏和2栏 13种可选颜色风格:基本上小清新的颜色都有了 3种列表模式:多图展示、单图展示、无图展示 7...

    magento开发教程

    1.Magento的配置系统 4 ...9.3延迟加载(Lazy Loading) 84 9.4过滤数据(Filtering Database Collections) 85 9.5比较运算符,构造Sql语句 86 9.6总结 89 10.技能考核 89 10.1理论考核 89 10.2实战考核 89

    ssh(structs,spring,hibernate)框架中的上传下载

    这是Hibernate3引入的新特性,对于包含重量级大数据的表字段,这种抽取方式提高了对大字段操作的灵活性,否则加载Tfile对象的结果集时如果总是返回fileContent,这种批量的数据抽取将可以引起数据库的"洪泛效应"。...

    cms后台管理

    三 首页的加载过程 在浏览器中输入http://localhost:8080/jeecms,回车 首先进入配置文件web.xml, &lt;context-param&gt; &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt; &lt;!----&gt; &lt;param-value&gt; /WEB-INF/...

    hibernate 框架详解

    三种策略 10.1.1. 每个类分层结构一张表(Table per class hierarchy) 10.1.2. 每个子类一张表(Table per subclass) 10.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 10.1.4. 混合...

    hibernate3.04中文文档.chm

    10.1. 三种策略 10.1.1. 每个类分层结构一张表(Table per class hierarchy) 10.1.2. 每个子类一张表(Table per subclass) 10.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 10.1.4. ...

    Hibernate教程

    10.1. 三种策略 10.1.1. 每个类分层结构一张表(Table per class hierarchy) 10.1.2. 每个子类一张表(Table per subclass) 10.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 10.1.4. ...

Global site tag (gtag.js) - Google Analytics