Hibernate性能调优--关联实体的延迟加载
来源:互联网 发布:电子音乐制作软件下载 编辑:程序博客网 时间:2024/05/20 23:07
默认情况下,Hibernate也会采用延迟加载来加载关联实体,不管是一对多关联、还是一对一关联、多对多关联,Hibernate 默认都会采用延迟加载。
对于关联实体,可以将其分为两种情况:
- 关联实体是多个实体时(包括一对多、多对多):此时关联实体将以集合的形式存在,Hibernate将使用 PersistentSet、PersistentList、PersistentMap、PersistentSortedMap、PersistentSortedSet等集合来管理延迟加载的实体。这就是前面所介绍的情形。
- 关联实体是单个实体时(包括一对一、多对一):当 Hibernate加载某个实体时,延迟的关联实体将是一个动态生成代理对象。
当关联实体是单个实体时,也就是使用<many-to-one.../> 或 <one-to-one.../> 映射关联实体的情形,这两个元素也可通过 lazy属性来指定延迟加载。
下面例子把Address 类也映射成持久化类,此时 Address 类也变成实体类,Person 实体与 Address实体形成一对多的双向关联。此时的映射文件代码如下:
Person.hbm.xml
<hibernate-mappingpackage="org.crazyit.app.domain">
<classname="Person" table="person_inf">
<idname="id" column="person_id">
<generatorclass="identity" />
</id>
<propertyname="name" type="string" />
<propertyname="age" type="int" />
<!--映射集合属性,集合元素是其他持久化实体没有指定 cascade属性,指定不控制关联关系 -->
<setname="addresses" inverse="true">
<!--指定关联的外键列-->
<keycolumn="person_id" />
<!--用以映射到关联类属性 -->
<one-to-manyclass="Address" />
</set>
</class>
<!--映射Address持久化类 -->
<classname="Address" table="address_inf">
<!--映射标识属性addressId -->
<idname="addressId" column="address_id">
<!--指定主键生成器策略 -->
<generatorclass="identity" />
</id>
<!--映射普通属性detail -->
<propertyname="detail" />
<!--映射普通属性zip -->
<propertyname="zip" />
<!--必须指定列名为person_id,与关联实体中 key元素的column属性值相同 -->
<many-to-onename="person" class="Person" column="person_id"
not-null="true"/>
</class>
</hibernate-mapping>
接下来程序通过如下代码片段来加载ID 为 1 的 Person 实体:
//打开上下文相关的 Session
Session session = sessionFactory.getCurrentSession();
Transaction tx =session.beginTransaction();
Address address = (Address)session.get(Address.class , 1); //<1>
System.out.println(address.getDetail());
为了看到 Hibernate 加载 Address 实体时对其关联实体的处理,我们在 <1>号代码处设置一个断点,在 Eclipse中进行 Debug,此时可以看到 Eclipse的 Console 窗口输出如下 SQL语句:
select
address0_.address_id asaddress1_1_0_,
address0_.detail as detail1_0_,
address0_.zip as zip1_0_,
address0_.person_id asperson4_1_0_
from
address_inf address0_
where
address0_.address_id=?
从这条SQL 语句不难看出,Hibernate 加载 Address 实体对应的数据表抓取记录,并未从 Person实体对应的数据表中抓取记录,这是延迟加载发挥了作用。
从Eclipse 的 Variables 窗口看到如图所示的输出:
延迟加载的实体
从图可以清楚地看到,此时Address 实体所关联的 Person 实体并不是 Person 对象,而是一个 Person_$$_javassist_0 类的实例,这个类是Hibernate 使用 Javassist 项目动态生成的代理类——当 Hibernate 延迟加载关联实体时,将会采用 Javassist生成一个动态代理对象,这个代理对象将负责代理“暂未加载”的关联实体。
只要应用程序需要使用“暂未加载”的关联实体,Person_$$_javassist_0代理对象会负责去加载真正的关联实体,并返回实际的关联实体——这就是最典型的代理模式。
单击图所示Variables 窗口中的 person 属性(也就是在调试模式下强行使用 person 属性),此时看到 Eclipse 的 Console窗口输出如下的 SQL 语句:
select
person0_.person_id asperson1_0_0_,
person0_.name as name0_0_,
person0_.age as age0_0_
from
person_inf person0_
where
person0_.person_id=?
上面SQL 语句就是去抓取“延迟加载”的关联实体的语句。此时可以看到 Variables 窗口输出图所示的结果:
已加载的实体
Hibernate采用“延迟加载”管理关联实体的模式,其实就在加载主实体时,并未真正去抓取关联实体对应数据,而只是动态地生成一个对象作为关联实体的代理。当应用程序真正需要使用关联实体时,代理对象会负责从底层数据库抓取记录,并初始化真正的关联实体。
在Hibernate 的延迟加载中,客户端程序开始获取的只是一个动态生成的代理对象,而真正的实体则委托给代理对象来管理——这就是典型的代理模式。
- Hibernate性能调优--关联实体的延迟加载
- Hibernate性能调优--集合属性的延迟加载
- Hibernate中的延迟加载、实体关联单向一对多及双向一对多实体关联
- Hibernate3 实体属性的延迟加载——Hibernate深入浅出
- Hibernate关联映射关系下的延迟加载剖析
- hibernate的延迟加载和关联数据抓取方式
- hibernate复习4 延迟加载1--实体
- Hibernate实现实体对象延迟加载(转载)
- 浅析Hibernate实现实体对象延迟加载
- hibernate实体配置关系映射&延迟加载
- hibernate的延迟加载
- Hibernate的延迟加载
- hibernate 的延迟加载
- hibernate的延迟加载
- hibernate的延迟加载
- Hibernate 的延迟加载
- Hibernate的延迟加载
- Hibernate的延迟加载
- 初始配置CentOS 7服务器
- python中的argparse模块(参数解析)
- CF 9C Hexadecimal's Numbers
- Android教程(二)--基本控件TextView的使用
- Linux-Nginx-关闭进程
- Hibernate性能调优--关联实体的延迟加载
- scala之尾递归实际用处2
- Visual Assist X 10.8.2048.0破解教程
- HDU 2034 人见人爱A-B
- ARCH64:怎样恢复函数的栈
- 我的博客,我的梦想
- C语言复杂声明,指令函数
- 学习笔记-基础知识8-集合框架(1)上
- 如何定位Android NDK开发中遇到的错误(内附我的总结补充)