Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载。Hibernate 通过这种延迟加载来降低系统的内存开销,从而保证 Hibernate 的运行性能。
如果想对实体对象使用延迟加载,必须要在实体的映射配置文件中进行相应的配置,如下所示:
book和user是多对一的关系,一个用户可以有很多书。 根据外键对应。
<hibernate-mapping> <class name="com.hibernate.domain.Users" table="users"> <id name="id" column="ID" type="java.lang.String"> <generator class="uuid.hex"/> </id> <set name="Books" inverse="true" cascade="all"> <key><column name="userId" /></key> <one-to-many class="com.hibernate.domain.Books" /> </set> <set name="includedUsers" table="USER_DEPARTMENT" schema="oracleUsername" inverse="true"> <key column="DEPARTMENT_ID" /> <many-to-many class="com.hibernate.domain.Users" column="USER_ID" /> </set> <property name="totalCount" type="java.lang.Integer" formula="(SELECT COUNT(*) FROM BOOKS WHERE USER_ID = ID)" /> </class> <class name="com.hibernate.domain.Books" table="Books"> <many-to-one name="Users" class="com.hibernate.domain.Users" fetch="select" insert="false" update="false"> <column name="userId" /> </many-to-one> </class> </hibernate-mapping>
通过将class的lazy属性设置为true,来开启实体的延迟加载特性。上面映射文件中 <set.../> 元素里的代码指定了 lazy="true"(对于 <set.../> 元素来说,lazy="true"是默认值),它指定 Hibernate 会延迟加载集合属性里 Books 对象。
private Set Books = new HashSet(0); private Set<User> includedUsers = new HashSet<User>(0);
Users instance = (Users) getSession().get("com.hibernate.Users", id); Set Books = instance.getBookes();会把user表中对应的Books记录查询出来,使用延迟检索。得到的是一个set集合。
默认情况下,Hibernate 也会采用延迟加载来加载关联实体,不管是一对多关联、还是一对一关联、多对多关联,Hibernate 默认都会采用延迟加载。
对于关联实体,可以将其分为两种情况:
(1)关联实体是多个实体时(包括一对多、多对多):此时关联实体将以集合的形式存在,Hibernate将使用PersistentSet、PersistentList、PersistentMap、PersistentSortedMap、PersistentSortedSet 等集合来管理延迟加载的实体。这就是前面所介绍的情形。
(2)关联实体是单个实体时(包括一对一、多对一):当 Hibernate 加载某个实体时,延迟的关联实体将是一个动态生成代理对象。
当关联实体是单个实体时,也就是使用 <many-to-one.../> 或 <one-to-one.../> 映射关联实体的情形,这两个元素也可通过 lazy 属性来指定延迟加载。
Hibernate 的延迟加载(lazy load)本质上就是代理模式的应用,我们在过去的岁月里就经常通过代理模式来降低系统的内存开销、提升应用的运行性能。Hibernate 充分利用了代理模式的这种优势,并结合了 Javassist 或 CGLIB 来动态地生成代理对象,这更加增加了代理模式的灵活性,Hibernate 给这种用法一个新名称:延迟加载。无论怎样,充分分析、了解这些开源框架的实现可以更好的感受经典设计模式的优势所在。