本节内容:
- l 掌握延迟策略概念
- l 掌握实体对象的延迟加载
- l 掌握集合类型的延迟加载
- l 了解属性延迟加载
1 延迟策略概念
- 延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。
- 在Hibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在Hibernate3中还提供了对属性的延迟加载。
- Hibernate中的延迟加载策略只有在session打开的状态下有效。
2 实体对象延迟加载
如果想对实体对象使用延迟加载,必须要在实体的映射配置文件中进行相应的配置,如下所示:
<!-- class的lazy属性设为true,则为实体的延迟加载 --> <class name="com.silvan.pojo.News" table="news" lazy="true"> <id name="id"> <generator class="native"></generator> </id> <property name="title" /> <property name="content" /> </class>
插入数据后使用下面代码进行查询测试:
public void query(){ Session session = HibernateUtil.getSession(); Transaction tx = null; try{ tx = session.beginTransaction(); News news=(News)session.load(News.class,21);//(1) System.out.println(news.getTitle());//(2) }catch(Exception e){ if(tx!=null){ tx.rollback(); } e.printStackTrace(); }finally{ HibernateUtil.closeSession(session); } }
解析:
- 当运行到(1)处时,Hibernate并没有发起对数据的查询,如果我们此时通过一些调试工具,观察此时news对象的内存快照,我们会惊奇的发现,此时返回实体对象的代理类对象,这里所返回的对象类型就是News对象的代理类对象。
- 当代码运行到(2)处时,此时调用news.getTitle() 方法,发出Sql语句进行查询。
- 这样,通过一个中间代理对象,Hibernate实现了实体的延迟加载,只有当用户真正发起获得实体对象属性的动作时,才真正会发起数据库查询操作。所以实体的延迟加载是用通过中间代理类完成的,所以只有session.load()方法才会利用实体延迟加载,因为只有session.load()方法才会返回实体类的代理类对象。
3 集合类型的延迟加载
- 在Hibernate的延迟加载机制中,针对集合类型的应用,意义是最为重大的,因为这有可能使性能得到大幅度的提高,我们在一对多关联中,定义用来容纳关联对象的Set集合,并不是java.util.Set类型或其子类型,而是net.sf.hibernate.collection.Set类型,通过使用自定义集合类的实现,Hibernate实现了集合类型的延迟加载。
- 要求News类中写private Set editor;具体实现类让Hibernate赋予。
为了对集合类型使用延迟加载,我们必须如下配置集合的关联部分:
<!-- 集合的lazy属性设置为true,则为集合类型的延迟加载--> <set name="editor" table="editor" lazy="true"> <key column="id"></key> <element type="string" column="name"></element> </set>
通过将<set>元素的lazy属性设置为true来开启集合类型的延迟加载特性。
我们看下面插入数据和查询的测试代码:
//插入 News news = new News(); news.setTitle("title"); news.setContent("content"); Set editor = new HashSet(); editor.add("qinqin1"); editor.add("qinqin2"); news.setEditor(editor); session.save(news); //查询 News news=(News)session.get(News.class,1); //当集合lazy属性为true,只有在调用集合的时候才会执行集合查询语句,与使用get或load无关 Set editor = news.getEditor();//(1) for(Object obj:editor){//(2) System.out.println(obj.toString()); }
解析:
当程序执行到(1)处时,这时并不会发起对关联数据的查询来加载关联数据,只有运行到(2)处时,真正的数据读取操作才会开始,这时Hibernate会根据缓存中符合条件的数据索引,来查找符合条件的实体对象。
4 属性的延迟加载
- 在Hibernate3中,引入了一种新的特性——属性的延迟加载,这个机制又为获取高性能查询提供了有力的工具。在前面我们讲大数据对象读取时,在User对象中有一个resume字段,该字段是一个java.sql.Clob类型,包含了用户的简历信息,当我们加载该对象时,我们不得不每一次都要加载这个字段,而不论我们是否真的需要它,而且这种大数据对象的读取本身会带来很大的性能开销。
- 在Hibernate3中,我们可以通过属性延迟加载机制,来使我们获得只有当我们真正需要操作这个字段时,才去读取这个字段数据。
- 属性的延迟加载用的少,故了解