前言
这一篇主要记录了Hibernate中的加载策略,通过在xml中的不同配置,我们可以设置不同的加载策略。加载策略一般分为延迟加载和立即加载,延迟加载是在使用的时候才会加载数据,立即加载是不管使用不使用,都会立刻加载数据。
一、两种级别的加载策略
加载策略分为类级别加载策略和关联级别加载策略。
类级别加载策略比较简单,最常见的列子就是,load和get这两个方法。在Hibernate学习笔记-环境配置以及常用对象这篇中有介绍过这两种方法的区别,get方法其实就是立即加载,它会立即查询数据库,将数据初始化。而load方法,在默认的设置下(在class标签中,lazy默认值为true),是一个延迟加载,它会返回一个代理对象,使用代理对象的属性时,才去查数据库;如果把lazy的值设置为false,那么load将会和get方法一样。
对于load的lazy属性的设置实例如下:
<hibernate-mapping package="com.hibern.pojo">
<!--在class标签中加上lazy属性-->
<class name="Customer" table="t_customer" lazy="false">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name" type="string"></property>
<set name="orders">
<key column="cid"></key>
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
关联级别的加载一般用于一对多关系中,这里要注意的是,我们可以在一的关系那一边设置加载策略,也可以在多的关系那一边设置加载策略。
二、关联级别的加载策略(一对多)
1. lazy属性和fetch属性
下面的列子以从客户表找订单为案例,来看下加载策略的几种情况(这里加载策略的属性主要配置在set标签内的)。
<hibernate-mapping package="com.hibern.pojo">
<class name="Customer" table="t_customer" lazy="false">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name" type="string"></property>
<!--set中有两个属性和加载有关,分别是lazy和fetch,这里没有填写具体的值,每个值代表什么意思下面的内容会具体分析-->
<set name="orders" lazy="xxx" fetch="xxx">
<key column="cid"></key>
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
- lazy:是否对set数据使用懒加载
true:默认值,对集合使用懒加载(在查询用户表的时候,不会查询该用户关联的订单,只有通过用户对象去获取订单对象的时候才会查询订单表)
false:集合会被立刻加载(情况就与上面相反)
(上面的截图是设置为false的情况,通过断点可以看到,当执行完15行的时候,此时打印的sql语句有两条,分别是查询了用户信息和用户的订单信息)
extra:极其懒惰(如果要获取某一用户的订单个数,即使用customer.getOrders().size(),不会查询订单的数据,只会用count去获取数量)
(这里可以看到,但我们执行完16行代码的时候,打印的语句是一条用count去查询的订单数量的sql;如果我们把extra改成true的话,这里将会打印查询订单完整信息的sql。) - fetch:决定加载集合使用的sql语句种类
select:默认值,普通select语句查询
join:表链接语句查询集合数据(此时查询的sql语句会是连接两个表的查询语句)
(在这里可以看到,同样的代码,当我们设置了fetch=join之后,打印的sql语句是一条连接查询的语句。)
subselect:使用子查询加载集合数据
(这里需要说明的是,子查询是要先查询出所有的用户,再遍历用户的时候,获取对应用户的订单信息的时候才能看到这样的效果。下面组合情况会具体展示示例代码。)
2. lazy属性和fetch属性的组合情况
lazy=true fetch=select:在使用集合的时候(执行第二行)才加载(每执行一行,分别打印对应的sql语句–查询用户数据和订单数据)
lazy=true fetch=join:查询用户表数据的时候就直接打印一条连接查询的sql语句(执行第一行,就会打印sql,且只打印这一条)
lazy=false fetch=select:查询用户数据的时候,就打印用户表的查询和订单表的查询的sql语句(执行第一行,直接打印两条select查询语句)
lazy=false fetch=join:查询用户表数据的时候就直接打印一条连接查询的sql语句(执行第一行,就会打印sql,且只打印这一条)
lazy=extra fetch=select:查询用户表时,打印一条查询语句,通过用户对象去获取订单数量时(执行第二行),不会查询订单的详细数据,只会用count获取数量
lazy=extra fetch=join:查询用户表数据的时候就直接打印一条连接查询的sql语句(执行第一行,就会打印sql,且只打印这一条)
(查询多个用户及其订单)
lazy=true fetch=subselect:使用集合时,才会加载,并且使用子查询的方式加载(执行第三行时,会使用一条子查询语句查询)
lazy=false fetch=subselect:查询用户数据时,也会立即用子查询查询其相关的订单信息
lazy=extra fetch=subselect:查询用户数据,打印一条sql语句查询用户表,查询订单数量的时候,会分别执行多条count语句查询每个用户的订单数;
上面的情况是针对,查询订单时只查询订单数量,对于需要查询订单具体信息时,如下图的代码所示:
(lazy=extra fetch=subselect这种组合情况打印的sql语句会有一些不同,对于需要获取订单数据的时候,会打印子查询获取)
三、在many-to-one标签中(多对一)
下面的列子,是以从订单找客户的角度。
- lazy:
false:加载订单时,会立刻加载客户数据
proxy:根据客户的类加载策略来决定 - fetch:
select:默认值,普通select语句查询加载
join:表链接语句查询集合数据
总结
以上就是Hibernate的加载策略设置的全部内容了。其实理解了每一个加载策略属性下不同值的意思,组合情况也就很好理解了。