Hibernate的延迟加载

7-09 2,831 views

简介

Hibernate通过延迟加载在真正需要使用数据时从数据库表中加载,这样可以加快程序运行速度,减少内存开销。Hibernate在以下三种情况会默认使用延迟加载:
1)load方法延迟加载;
2)实体属性延迟加载;
3)集合属性延迟加载。

数据库示例

1
示例数据库包含3张表:
1)文章表(post),存储文章标题、内容,主键为自增整数;
2)分类表(category),存储分类名称,主键为自增整数;
3)标签表(score),存储标签名称,主键为自增整数;
4)文章标签表(post_tag),存储文章包含的标签,使用文章id和标签id作为联合主键。
每篇文章属于一个分类,并包含多个标签。

延迟加载示例

创建Post类与post表映射。
Post.java:

Post.hbm.xml:

创建Category类与category表映射。
Category.java:

Category.hbm.xml:

创建Tag类与tag表映射。
Tag.java:

Tag.hbm.xml:

Hibernate配置文件hibernate.cfg.xml:

load方法延迟加载

创建测试类Test:

执行main方法,输出如下:

class of post: com.magicwt.bean.Post$$EnhancerByCGLIB$$70a21d16
Hibernate:
    select
        post0_.id as id1_0_,
        post0_.title as title1_0_,
        post0_.content as content1_0_
    from
        post post0_
    where
        post0_.id=?
title of post: 测试标题1

从中可以看出,load方法返回的是通过动态代理实现的代理类实例。通过断点可以观察到,执行“post.getTitle()”前,post实例各属性都是默认值(null或0),执行“post.getTitle()”后,才真正从数据库表中取出数据并输出。
将load方法修改为get方法并重新执行,输出如下:

Hibernate:
    select
        post0_.id as id1_0_,
        post0_.title as title1_0_,
        post0_.content as content1_0_
    from
        post post0_
    where
        post0_.id=?
class of post: com.magicwt.bean.Post
title of post: 测试标题1

从中可以看出,get方法返回的是Post类实例。通过断点可以观察到,get方法返回的post实例各属性已从数据库表中取出对应的值,get方法并没有延迟加载。

实体属性延迟加载

修改测试类Test:

执行main方法,输出如下:

Hibernate:
    select
        post0_.id as id1_0_,
        post0_.title as title1_0_,
        post0_.content as content1_0_
    from
        post post0_
    where
        post0_.id=?
class of post: com.magicwt.bean.Post
class of category: com.magicwt.bean.Category$$EnhancerByCGLIB$$483428f6
Hibernate:
    select
        category0_.id as id0_0_,
        category0_.name as name0_0_
    from
        category category0_
    where
        category0_.id=?
name of category: 测试分类1

从中可以看出,get方法返回的post实例,其属性category是代理类实例,并没有真正读取category表中的数据,只有在输出分类名称时,才读取category表中的数据。

集合属性延迟加载

修改测试类Test:

执行main方法,输出如下:

Hibernate:
    select
        post0_.id as id1_0_,
        post0_.title as title1_0_,
        post0_.content as content1_0_
    from
        post post0_
    where
        post0_.id=?
class of post: com.magicwt.bean.Post
class of tags: org.hibernate.collection.PersistentSet
Hibernate:
    select
        tags0_.post_id as post1_1_,
        tags0_.tag_id as tag2_1_,
        tag1_.id as id3_0_,
        tag1_.name as name3_0_
    from
        post_tag tags0_
    left outer join
        tag tag1_
            on tags0_.tag_id=tag1_.id
    where
        tags0_.post_id=?
name of tag: 测试标签1
name of tag: 测试标签2

从中可以看出,get方法返回的post实例,其属性tags是PersistentSet实例,并没有真正读取tag表中的数据,只有在输出标签名称时,才读取tag表中的数据。

标签:

基于WebSocket实现微信小程序的消息推送

微信小程序支持通过基于WebSocket进行消息推送,提供了相应的API,例如创建连接示例代码: JavaScript wx.connectSocket({ ...

阅读全文

基于nginx-sticky-module-ng实现会话保持(Sticky Sessions)

对服务进行集群部署,前端进行负载均衡时,需要实现会话保持,对于同一会话的多个请求,通过集群中的一个节点来提供服务。系统的部署结构如图所示,通过Resin...

阅读全文

ActiveMQ基于Zookeeper和LevelDB实现Master/Slave

ActiveMQ的Master/Slave目前支持三种实现方式: 1)Shared File System Master Slave; 2)JDBC Master Slave; 3)Replicated LevelDB Store。 对于第三种方...

阅读全文