类级别的检索策略
类级别可选的检索策略包括立即检索和延迟检索,默认为延迟检索
- 立即检索:立即加载检索方法指定的对象
- 延迟检索:延迟加载检索方法指定的对象,在使用具体的属性时,再进行加载
类级别的检索策略可以通过<class>
元素的lazy
属性进行设置
-
lazy
为true
时,就是延迟检索。 -
lazy
为false
时,就是立即检索。
如果程序加载一个对象的目的是为了访问它的属性,可以采取立即检索。如果程序加载一个持久化对象的目的是仅仅为了获得它的引用,可以采取延迟检索,在使用延迟检索时,要防止懒加载异常。
无论<class>
的元素的lazy
属性是true
还是false
,Session的get()
及Query的list()
在类级别总是使用立即检索策略。
若<class>
元素的lazy
属性为true
或取默认值,Session的load()
不会执行查询数据表的SELECT语句,仅返回代理类对象的实例,该代理类实例有如下特征:
- 由Hibernate在运行时采用CGLIB工具动态生成
- Hibernate创建代理类实例时,仅初始化其OID属性
- 在应用程序第一次访问代理类实例的非OID属性时,Hibernate会初始化代理类实例。
延迟检索和增强延迟检索
在延迟检索(lazy
属性为true
)集合属性时,Hibernate在以下情况下初始化集合代理类实例
- 应用程序第一次访问集合属性:
iterator()
,size()
,isEmpty()
,contains()
等方法 - 通过
Hibernate.initialize()
静态方法显示初始化
增强延迟检索(lazy
属性为extra
)时,与延迟检索类似,主要区别是增强延迟检索策略能进一步延迟实体类对象的集合代理实例的初始化时机。
- 当程序第一次访问集合属性的
iterator()
时,会导致集合代理类实例的初始化 - 当程序第一次访问集合属性的
size()
,contains()
,isEmpty()
时,Hibernate不会初始化集合类的实例,仅通过特定的SELECT语句查询必要的信息,不会检索所有的集合对象。
一对多和多对多的检索策略
在映射文件中,用<set>
元素来配置一对多关联及多对多关联关系,<set>
元素有lazy
和fetch
属性。
-
lazy
:主要决定实体类中关联的集合被初始化的时机。即到底是在加载实体类对象的时候就被初始化呢,还是在程序访问集合时被初始化。
默认为true
,即访问集合时被初始化,可以设置为false
,即加载实体类对象的时候就初始化。lazy
还可以设置为extra
,是一个增强版的延迟检索,会尽可能地延迟集合初始化的时机。 -
<set>
元素的batch-size
属性
用来为延迟检索策略或立即检索策略设定批量检索的数量。批量检索能减少SELECT语句的数目,提高延迟检索或立即检索的运行性能。
配置示例:
<!-- 一次性检索5个集合-->
<set name="orders" table="orders" inverse="true" cascade="delete" batch-size="5">
<key column="customer_id"></key>
<one-to-many class="Order"/>
</set>
-
fetch
:决定初始化集合的方式。
取值为select
或subselect
时,决定初始化集合的查询语句的方式,subselect
是子查询,此时batch-size
属性将被忽略;若取值为join
,则决定集合被初始化的时机。在加载一端的实体类对象时,使用迫切左外连接(使用左外连接进行查询,且把集合属性进行初始化)的方式检索n端的集合属性若把fetch
设置为join
的话,lazy
属性将被忽略。若使用HQL查询,则忽略fetch=join
。
多对一和一对一关联的检索策略
和set
一样,<many-to-one>
元素也有一个lazy
属性和fetch
属性
lazy属性(默认值为proxy) | fetch属性(默认值为select) | 检索实体对象时对关联的实体对象使用的检索策略 |
---|---|---|
proxy | 未显式设置(默认值为select) | 采取延迟检索 |
no-proxy | 未显式设置(默认值为select) | 无代理延迟检索 |
false | 未显式设置(默认值为select) | 立即检索 |
未显式设置(默认值为proxy) | join | 迫切左外连接策略 |
-
若
fetch
属性设为join
,那么lazy
属性被忽略,并且使用迫切左外连接来初始化n端关联的1端的属性 -
迫切左外连接检索策略的优点在于比立即检索策略使用的SELECT更少
-
无代理延迟检索需要增强持久化类的字节码才能实现
-
Query
的list()
会忽略映射文件配置的迫切左外连接检索策略,而采用延迟检索策略 -
batch-size
:一次性初始化1端的代理对象的个数。该属性需要设置在1端的class元素中
示例:<class name="Customer" table="customers" batch-size="5">
关联级别运行时的检索策略
- 如果在HQL中没有显式指定检索策略,将使用映射文件配置的检索策略。
- HQL会忽略映射文件中设置的迫切左外连接检索策略。如果希望HQL采用迫切左外连接检索策略,就必须在HQL查询语句中显示的指定它。
- 若在HQL代码中显示指定了检索策略,就会覆盖映射文件中配置的检索策略。
网友评论