2011-12-24 13:58 242人阅读 评论(0) 收藏 举报

Hibernate对象关系映射提供延迟的与非延迟的对象初始化。非延迟加载在读取一个对象的时候会将与这个对象所有相关的其他对象一起读取出来。这有时会导致成百的(如果不是成千的话)select语句在读取对象的时候执行。这个问题有时出现在使用双向关系的时候,经常会导致整个数据库都在初始化的阶段被读出来了。当然,你可以不厌其烦地检查每一个对象与其他对象的关系,并把那些最昂贵的删除,但是到最后,我们可能会因此失去了本想在ORM工具中获得的便利。一个明显的解决方法是使用Hibernate提供的延迟加载机制。这种初始化策略只在一个对象调用它的一对多或多对多关系时才将关系对象读取出来。这个过程对开发者来说是透明的,而且只进行了很少的数据库操作请求,因此会得到比较明显的性能提升。这项技术的一个缺陷是延迟加载技术要求一个Hibernate会话要在对象使用的时候一直开着。这会成为通过使用DAO模式将持久层抽象出来时的一个主要问题。为了将持久化机制完全地抽象出来,所有的数据库逻辑,包括打开或关闭会话,都不能在应用层出现。最常见的是,一些实现了简单接口的DAO实现类将数据库逻辑完全封装起来了。一种快速但是笨拙的解决方法是放弃DAO模式,将数据库连接逻辑加到应用层中来。这可能对一些小的应用程序有效,但是在大的系统中,这是一个严重的设计缺陷,妨碍了系统的可扩展性。在Web层进行延迟加载幸运的是,Spring框架为Hibernate延迟加载与DAO模式的整合提供了一种方便的解决方法。对那些不熟悉Spring与Hibernate集成使用的人,我不会在这里讨论过多的细节,但是我建议你去了解Hibernate 与Spring集成的数据访问。以一个Web应用为例,Spring提供了OpenSessionInViewFilter和 OpenSessionInViewInterceptor。我们可以随意选择一个类来实现相同的功能。两种方法唯一的不同就在于interceptor 在Spring容器中运行并被配置在web应用的上下文中,而Filter在Spring之前运行并被配置在web.xml中。不管用哪个,他们都在请求将当前会话与当前(数据库)线程绑定时打开Hibernate会话。一旦已绑定到线程,这个打开了的Hibernate会话可以在DAO实现类中透明地使用。这个会话会为延迟加载数据库中值对象的视图保持打开状态。一旦这个逻辑视图完成了,Hibernate会话会在Filter的doFilter方法或者Interceptor的postHandle方法中被关闭。下面是每个组件的配置示例: Interceptor的配置: Filter的配置 hibernateFilter org.springframework.orm.hibernate.support.OpenSessionInViewFilter hibernateFilter *. spring 实现Hibernate的Dao接口来使用打开的会话是很容易的。事实上,如果你已经使用了Spring框架来实现你的Hibernate Dao,很可能你不需要改变任何东西。方便的HibernateTemplate公用组件使访问数据库变成小菜一碟,而DAO接口只有通过这个组件才可以访问到数据库。下面是一个示例的DAO: public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO { public Product getProduct(Integer productId) { return (Product)getHibernateTemplate().load(Product.class, productId); } public Integer saveProduct(Product product) { return (Integer) getHibernateTemplate().save(product); } public void updateProduct(Product product) { getHibernateTemplate().update(product); } } 在业务逻辑层中使用延迟加载即使在视图外面,Spring框架也通过使用AOP 拦截器 HibernateInterceptor来使得延迟加载变得很容易实现。这个Hibernate 拦截器透明地将调用配置在Spring应用程序上下文中的业务对象中方法的请求拦截下来,在调用方法之前打开一个Hibernate会话,然后在方法执行完之后将会话关闭。让我们来看一个简单的例子,假设我们有一个接口BussinessObject: public interface BusinessObject { public void doSomethingThatInvolvesDaos(); } 类BusinessObjectImpl实现了BusinessObject接口: public class BusinessObjectImpl implements BusinessObject { public void doSomethingThatInvolvesDaos() { // lots of logic that calls // DAO classes Which access // data objects lazily } } 通过在Spring应用程序上下文中的一些配置,我们可以让将调用BusinessObject的方法拦截下来,再令它的方法支持延迟加载。看看下面的一个程序片段: com.acompany.BusinessObject hibernateInterceptor 当businessObject被调用的时候,HibernateInterceptor打开一个Hibernate会话,并将调用请求传递给BusinessObjectImpl对象。当 BusinessObjectImpl执行完成后,HibernateInterceptor透明地关闭了会话。应用层的代码不用了解任何持久层逻辑,还是实现了延迟加载。在单元测试中测试延迟加载最后,我们需要用J-Unit来测试我们的延迟加载程序。我们可以轻易地通过重写TestCase类中的setUp和tearDown方法来实现这个要求。我比较喜欢用这个方便的抽象类作为我所有测试类的基类。 public abstract class MyLazyTestCase extends TestCase { private SessionFactory sessionFactory; private Session session; public void setUp() throws Exception { super.setUp(); SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory"); session = SessionFactoryUtils.getSession(sessionFactory, true); Session s = sessionFactory.openSession(); TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s)); } protected Object getBean(String beanName) { //Code to get objects from Spring application context } public void tearDown() throws Exception { super.tearDown(); SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); Session s = holder.getSession(); s.flush(); TransactionSynchronizationManager.unbindResource(sessionFactory); SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory); } } 我们首先说利用lazy=false来解决问题,这种方法是很好用,但是在实际的过程并不实用,如果你某个对象关联好几个甚至十几个自对象,那么每次加载一个的话要执行很多HQL语句,可想而知这个效率问题啦,特别是在使用列表的时候。所以不实用,而在上述所说的“在业务逻辑层中使用延迟加载” 也是这种情况吧。很多使用WEB的朋友都喜欢利用openSessionView来加载这个问题。不错我也喜欢用,简单方便。但是说几种情况: 1.在quartz中总不能使用openSessionView模式吧 2.在spring后拦截的过程中,如果取拦截对象中的子对象利用openSessionView也不行

解决方案:如果是在one的一方查询many,在one的一方的set方法里加入属性:lazy="false";

如果是在many的一方查询one,在many的一方的many-to-one里加上lazy="false";

@原文转载:http://blog.csdn.net/ping159/article/details/7099579

Hibernate是如何延迟加载的的更多相关文章

  1. Hibernate学习之延迟加载

    转自:http://www.cnblogs.com/xiaoluo501395377/p/3371776.html 在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通 ...

  2. Hibernate中的延迟加载及fetch

    Hibernate中的延迟加载 1.类级别的查询策略: lazy  :  true(默认值) false(立即加载) 2.多对一关联的查询策略: lazy:  proxy(默认值) no-proxy ...

  3. Hibernate之lazy延迟加载

    一.延迟加载的概念 当Hibernate从数据库中加载某个对象时,不加载关联的对象,而只是生成了代理对象,获取使用session中的load的方法(在没有改变lazy属性为false的情况下)获取到的 ...

  4. Hibernate之lazy延迟加载(转)

    一.延迟加载的概念 当Hibernate从数据库中加载某个对象时,不加载关联的对象,而只是生成了代理对象,获取使用session中的load的方法(在没有改变lazy属性为false的情况下)获取到的 ...

  5. 【Hibernate】浅析hibernate中的延迟加载

    1 简介 在使用一些查询方法时,方法执行了,但是并没有立刻发送SQL语句查询数据库.而是在访问对象的getXxx方法时候才触发SQL执行加载对象数据.这种机制就称为延迟加载. 2 优点 延迟加载主要是 ...

  6. Hibernate lazy(延迟加载)

    Hibernat加载策略有两种,分别为即时加载和延迟加载(懒加载或者lazy),get使用的是即时加载,使用get获取数据时会立即查找(会先去缓存查找,如果缓存中没有找到,才会去数据库中查找),而lo ...

  7. (十六)Hibernate中的延迟加载

    一.什么是延迟加载 为了节省Hibernate加载对象的性能节销,在Hibernate中真正需要用到这个对象时,才会发出        SQL语句来抓取这个对象.这一个过程称为延迟加载. 二.延迟加载 ...

  8. Hibernate检索策略之延迟加载和立即加载

    延迟加载:延迟加载(lazy load懒加载)是当在真正需要数据时,才执行SQL语句进行查询.避免了无谓的性能开销. 延迟加载分类:  1.类级别的查询策略 2.一对多和多对多关联的查询策略 3.多对 ...

  9. Hibernate的延迟加载

    我们会分析load和get两种加载方式: 一.load加载方式 当使用load方法来得到一个对象时,此时hibernate会使用延迟加载的机制来加载这个对象,即:当我们使用session.load() ...

随机推荐

  1. POJ3041:Asteroids【二分图匹配】

    二分图的最大匹配=最小顶点覆盖(Konig定理)=最大独立集的补集最大匹配经典的三种模型  这题就是最小顶点覆盖,顺便这题留给我的经验就是调试的时候一定要细心细心再细心对模板的各个细节都要熟!! #i ...

  2. SeLion数据驱动中遇到的问题,以及解决方案

    问题描述: 使用selion框架数据驱动时,总是test ignored. 解决方案: 把这个dataprovider方法拿出来做单元测试.有详细报错. 问题1:使用wps保存,poi包只能解析xls ...

  3. MySQL基础架构

    前段时间订阅了<Mysql实战45讲>(从原理到实战),新的一年为自己充充电.对于这部分内容,我所知道的只来源于我大学里学习的课程<数据库原理>,在大学里学习的只是简单的查询, ...

  4. Hadoop经典书籍资料收藏(35本)转

    原文地址:http://www.hadoopor.com/thread-5128-1-2.html 1."Hadoop.Operations.pdf.zip" http://vdi ...

  5. HDU 5360 【优先队列+贪心】

    题意: 给定N个无序区间. 对合法区间的定义是: 在这个区间之前已经选出了至少l个合法区间,最多选出了r个合法区间.则该区间为合法区间. 输出最多能挑选出多少个合法区间,并输出合法区间的数量. 思路: ...

  6. asterisk 相关数据库配置 使用

    Linux/Unix下ODBC的安装: 先下载最新的unixODBC源码包(http://www.unixodbc.org/unixODBC-2.2.1.tar.gz)放到/usr/local下,然后 ...

  7. PLSQL安装资料

    一.plsql developer 注册码 plsql developer 10 注册码 product code :4v6hkjs66vc944tp74p3e7t4gs6duq4m4szbf3t38 ...

  8. struts2 自己定义表单

    自己定义表单一定会涉及<s:iterator/>迭代,一个复杂的自己定义表单可能会嵌套n多层迭代. 比方一个自己定义一个问卷调查页面涉及3个模型:一个Survey代表一个调查.一个Page ...

  9. zz年度热门编程语言排行榜

    原文在这里:Link 蛮有意思的,可以看看.

  10. [Rust] Load a WebAssembly Function Written in Rust and Invoke it from JavaScript

    In this lesson we are going to setup a project from scratch by introducing the JavaScript snippet to ...