延迟加载(lazy load):应用只有在需要时才去数据库中抓取相应的记录。通过延迟加载技术可以避免过多、过早地加载数据表里的数据,从而降低应用的内存开销
如果对一个类或者集合配置了延迟检索策略,那么必须当代理类实例或代理集合处于持久化状态(即处于Session范围内)时,才能初始化它。如果在游离状态时才初始化它,就会产生延迟初始化错误。所以,在开发独立的DAO数据访问层时应该格外小心这个问题。
如果在获取对象的时候使用的是session.get()是不会延迟加载的,只有在使用load、hql时候才会延迟加载。
Hibernate中允许使用延迟加载的地方主要有以下几个地方:
<hibernate-mapping default-lazy=(true|false)>:设置全局的延迟加载策略。默认true
<class lazy=(true|false)>:默认值为true.只对普通属性起作用,对集合和<one-to-one> <many-to-one>不起作用
<property lazy=(true|false)>:设置字段延迟加载,默认为false.如果类设置了延迟加载,属性再设置无效。如果只对部分property进行延迟加载的话, hibernate还提供了另外的方式,也是更为推荐的方式,即HQL或者条件查询。
<many-to-one lazy=(proxy|no-proxy|false)>:默认为proxy
<one-to-one lazy=(proxy|no-proxy|false)>:默认为proxy
<set lazy=(true|extra|false)>:默认为true
<list lazy=(true|extra|false)>:默认为true
<map lazy=(true|extra|false)>:默认为true
<bag lazy=(true|extra|false)>:默认为true
<ibag lazy=(true|extra|false)>:默认为true
<component lazy=(true|false):默认为false
<subclass lazy=(true|false)>:默认设置为true
<join-subclass lazy=(true|false)>:默认设置为true
<union-subclass lazy=(true|false)>:默认设置为true
User.xml<hibernate-mapping>
<class name="wb.wk.review.mapping.onetomany.doubleMapping.Users" table="tbl_user" lazy="true">
<id name="id" column="id" type="java.lang.Integer">
<generator class="identity"></generator>
</id>
<property name="userName" type="java.lang.String" column="user_name"/>
<property name="password" type="java.lang.String" column="password"/>
<!-- 一对多双向关联
对于 <set.../> 元素来说,lazy="true"是默认值)
-->
<set name="bank" table="tbl_bank" cascade="all" inverse="true" lazy="extra">
<key column="user_id" /><!-- 确定关联的外键列 -->
<one-to-many class="wb.wk.review.mapping.onetomany.doubleMapping.Bank"/>
</set>
</class>
</hibernate-mapping>
Bank.xml
<hibernate-mapping>
<class name="wb.wk.review.mapping.onetomany.doubleMapping.Bank" table="tbl_bank">
<id name="id" column="id" type="java.lang.Integer">
<generator class="identity"></generator>
</id>
<property name="bankCard" type="java.lang.String" column="bank_card"/>
<!-- 一对多双向关联 -->
<many-to-one name="users" class="wb.wk.review.mapping.onetomany.doubleMapping.Users"
column="user_id" >
</many-to-one>
</class>
</hibernate-mapping>
测试Main:
Session session=null;
Transaction tran=null;
try {
session=HibernateSessionFactory.getSession();
tran=session.beginTransaction();
Users user=(Users) session.load(Users.class, 17);
System.out.println(user.getUserName());
user.getBank();
System.out.println(user.getBank().size());
} catch (HibernateException e) {
e.printStackTrace();
}finally{
session.flush();
session.close();
}
当使用extra 出现sql: select count(id) from tbl_bank where user_id =?
当使用 true,出现sql: select bank0_.user_id as user3_1_, bank0_.id as id1_,
bank0_.id as id1_0_, bank0_.bank_card as bank2_1_0_, bank0_.user_id as user3_1_0_
from tbl_bank bank0_ where bank0_.user_id=?
extra 调用集合的size/contains等方法的时候,hibernate 并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据.比如便利集合的时候。