为了避免一些情况下,关联关系所带来的无谓的性能开销。Hibernate引入了延迟加载的
概念。
如,示例中user对象在加载的时候,会同时读取其所关联的多个地址(address)对象,
对于需要对address进行操作的应用逻辑而言,关联数据的自动加载机制的确非常有效。
但是,如果我们只是想要获得user的性别(sex)属性,而不关心user的地址(address)
信息,那么自动加载address的特性就显得多余,并且造成了极大的性能浪费。为了获得user的性别属性,我们可能还要同时从数据库中读取数条无用的地址数据,这导致了大量无谓的系统开销。
延迟加载特性的出现,正是为了解决这个问题。
所谓延迟加载,就是在需要数据的时候,才真正执行数据加载操作。
对于我们这里的user对象的加载过程,也就意味着,加载user对象时只针对其本身的属性,
而当我们需要获取user对象所关联的address信息时(如执行user.getAddresses时),才真正从数据库中加载address数据并返回。
我们将前面一对多关系中的lazy属性修改为true,即指定了关联对象采用延迟加载:
<hibernate-mapping>
<class
name="org.hibernate.sample.TUser"
table="t_user"
dynamic-update="true"
dynamic-insert="true"
>
<set
name="addresses"
table="t_address"
lazy="true"
inverse="false"
cascade="all"
sort="unsorted"
order-by="zipcode asc"
>
<key
column="user_id"
>
</key>
<one-to-many
class="org.hibernate.sample.TAddress"
/>
</set>
……
</class>
</hibernate-mapping>
尝试执行以下代码:
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("name","Erica"));
List userList = criteria.list();
TUser user =(TUser)userList.get(0);
System.out.println("User name => "+user.getName());
Set hset = user.getAddresses();
session.close();//关闭Session
TAddress addr = (TAddress)hset.toArray()[0];
System.out.println(addr.getAddress());
运行时抛出异常:
LazyInitializationException - Failed to lazily initialize a collection - no session or session was closed
如果我们稍做调整,将session.close放在代码末尾,则不会发生这样的问题。
这意味着,只有我们实际加载user关联的address时,Hibernate才试图通过session从数据库中加载实际的数据集,而由于我们读取address之前已经关闭了session,所以报出session已关闭的错误。
这里有个问题,如果我们采用了延迟加载机制,但希望在一些情况下,实现非延迟加载时的功能,也就是说,我们希望在Session关闭后,依然允许操作user的addresses属性。如,为了向View层提供数据,我们必须提供一个完整的User对象,包含其所关联的address信息,而这个User对象必须在Session关闭之后仍然可以使用。
Hibernate.initialize方法可以通过强制加载关联对象实现这一功能:
Hibernate.initialize(user.getAddresses());
session.close();
//通过Hibernate.initialize方法强制读取数据
//addresses对象即可脱离session进行操作
Set hset= user.getAddresses();
TAddress addr = (TAddress)hset.toArray()[0];
System.out.println(addr.getAddress());
为了实现透明化的延迟加载机制,hibernate进行了大量努力。其中包括JDK Collection接口的独立实现。
如果我们尝试用HashSet强行转化Hibernate返回的Set型对象:
Set hset = (HashSet)user.getAddresses();
就会在运行期得到一个java.lang.ClassCastException,实际上,此时返回的是一个Hibernate的特定Set实现“net.sf.hibernate.collection.Set”对象,而非传统意义上的JDK Set实现。
这也正是我们为什么在编写POJO时,必须用JDK Collection接口(如Set,Map),
而非特定的JDK Collection实现类(如HashSet、HashMap)申明Collection属性的原因。
回到前面TUser类的定义:
public class TUser implements Serializable {
……
private Set addresses = new HashSet();
……
}
我们通过Set接口,申明了一个addresses属性,并创建了一个HashSet作为addresses的初始实例,以便我们创建TUser实例后,就可以为其添加关联的address对象:
TUser user = new TUser();
TAddress addr = new TAddress();
addr.setAddress("Hongkong");
user.getAddresses().add(addr);
session.save(user);
此时,这里的addresses属性还是一个HashSet对象,其中包含了一个address对象的引用。那么,当调用session.save(user)时,Hibernate是如何处理这个HashSet型属性的呢?
通过Eclipse的Debug窗口,我们可以看到session.save方法执行前后user对象发
生的变化:
首先,由于insert操作,Hibernate获得数据库产生的id值(在我们的例子中,采用native方式的主键生成机制),并填充到user对象的id属性。这个变化比较容易理解。
另一方面,Hibernate使用了自己的Collection实现“net.sf.hibernate.collection.Set”对user中的HashSet型addresses属性进
行了替换,并用数据对其进行填充,保证新的addresses与原有的addresses包含同样的实体元素。
由于拥有自身的Collection实现,Hibernate就可以在Collection层从容的实现延迟加载特性。只有程序真正读取这个Collection时,才激发底层实际的数据库操作。
分享到:
相关推荐
8. **延迟加载(Lazy Loading)**:Hibernate可以实现属性或关联关系的延迟加载,只有在真正需要时才从数据库中获取数据,避免了内存占用过多。 9. **增强型实体**:Hibernate 5引入了代理实体(Enhanced Entity)...
Vue-lazyload 就是一个专为 Vue.js 应用程序设计的插件,它允许我们按需加载图片,从而提高应用性能。 Vue-lazyload 插件主要解决了以下问题: 1. **减少网络资源请求**:传统方式下,所有图片都会在页面加载时...
Markdown-it-Lazy-Headers是前端开发领域的一个开源库,专门针对Markdown解析器Markdown-it设计的一款插件。这个插件的主要功能是实现"懒惰式"的ATX风格标题处理,也就是所谓的"Lazy ATX Headers"。在Markdown语法中...
2. `default-lazy`:默认情况下,未显式指定`lazy`属性的Java属性和集合将被懒加载,即在需要时才加载。如果设置为`false`,则这些属性和集合将在加载实体时立即加载。 3. `auto-import`:默认为`true`,允许在HQL...
Hibernate使用它来实现类的动态代理和字节码增强,例如懒加载(lazy loading)和CGLIB代理。 3. **antlr-2.7.7.jar**:ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。在...
前端项目-vanilla-lazyload,Lazyload是一个快速、轻量级和灵活的脚本,仅在图像即将进入可滚动区域的视区时才加载图像,并对渐进式JPEG图像格式提供了极好的支持。类型脚本模块定义可用。
- 注意懒加载(Lazy Loading)与级联操作的使用,防止“懒加载地狱”。 总结,`hibernate-release-4.3.10.Final`版本是Hibernate框架的一个重要里程碑,其提供的强大功能和优化特性使得Java开发者在处理数据库操作...
1. **延迟加载(Lazy Loading)增强**:Hibernate核心库已经支持延迟加载,但扩展可能提供了更精细的控制,例如按需加载关联的对象集合,减少内存占用和提高性能。 2. **批量操作**:批量插入、更新和删除功能可以...
8. **懒加载(Lazy Loading)**:一种优化策略,使得关联的对象在需要时才从数据库加载,避免不必要的性能开销。 9. **缓存**:Hibernate支持一级缓存(Session级别的)和二级缓存(SessionFactory级别的),可以...
Hibernate 支持懒加载(Lazy Loading),即延迟加载关联对象,直到真正需要时才从数据库加载,有效避免了"数据溢出"问题。它通过生成代理对象实现这一功能。 七、事件监听器 Hibernate 提供了一套事件监听系统,...
9. **延迟加载**(Lazy Loading):Hibernate支持延迟加载机制,当实体的一部分属性或关联对象没有立即使用时,不会立即加载,而是等到实际需要时再加载,从而优化性能。 10. **事件和监听器**:Hibernate允许...
### Hibernate 5.0.7.Final版本解析与应用指南 #### 一、概述 Hibernate 是一款开源的对象关系映射(Object-Relational Mapping,简称 ORM)框架,它为 Java 应用程序提供了对数据库存储的高效管理和访问能力。...
八、延迟加载(Lazy Loading) Hibernate支持懒加载策略,允许关联对象在需要时才加载,避免了不必要的数据库查询,提高了性能。 九、多对一、一对多、多对多关系 Hibernate通过外键映射和集合映射处理这些关系,如...
懒加载(Lazy Loading)是Hibernate的一大特性,它允许对象的关联属性在需要时才加载,从而减少数据库访问。立即加载(Eager Loading)则会在初始加载对象时,同时加载关联的数据。 七、事务处理 在Hibernate中,...
同时,它支持延迟加载(Lazy Loading),避免了内存消耗和性能瓶颈。 五、缓存策略 为了提高性能,Hibernate引入了缓存机制。一级缓存是Session级别的,所有在Session内的操作都会被缓存,直到事务提交。二级缓存则...
11. **延迟加载(Lazy Loading)**:Hibernate 3.2支持懒加载机制,对于一对多或多对一的关系,关联对象默认不会立即加载,而是在真正需要时才从数据库中获取,减少内存占用。 12. **事件监听器**:Hibernate提供了...
要使用Mocha-Lazy-BDD,首先需要安装Mocha和Mocha-Lazy-BDD库,可以通过npm进行安装: ``` npm install mocha mocha-lazy-bdd --save-dev ``` 然后在测试脚本中引入Mocha-Lazy-BDD,并按照其提供的语法编写测试...
8. **性能优化**: Hibernate提供了一些优化手段,如二级缓存、批处理、延迟加载(lazy loading)、预加载(eager loading)等,以提高应用性能。 9. **一对多、多对一、多对多关系映射**: Hibernate可以轻松处理...
Hibernate提供了多种性能优化策略,如延迟加载(Lazy Loading)、批处理(Batch Processing)、结果集缓存(Result Set Caching)等,旨在减少数据库交互,提高程序运行效率。 9. **关联映射** Hibernate支持多种...