当我们需要从数据库取一个A对象的时候,B(对象/集合)和A对象关联了,当我们访问A对象的时候,有可能把B也给加载出来,从而浪费了很多内存空间,所以有时候并不需要B,只需要得到的A,这就是立即加载和延迟加载的问题,延迟加载时,当我们使用该数据的时候,才会到数据库查询相对应的数据,立即加载的时候,在使用该数据之前就已经到数据库中查询过了
下面就拿一对多的例子来演示一下,User类和Order类,用户和订单的一对多的关系
<hibernate-mapping>
<class name="model.User" table="user" lazy="xxx">
上面是类的加载,lazy只有2种属性,一是true,如果不写lazy的话,默认也是true,表示延迟加载。二是false,表示立即加载。
因为User是属于一方,所以有一个Order集合,在配置文件种也有加载策略的配置
<set name="orders" fetch="xxx" lazy="xxx">
<key column="uid"></key>
<one-to-many class="model.Order" />
</set>而ordesr就是属于关联集合了,ftech的属性稍后说,先说说关联集合种lazy的属性,关联集合中有3中属性,除了之前见过的true和false之外,还有一个extra属性:加强版延迟加载,他和延迟加载有什么区别呢?比如
@Test
public void run4() {
Session session = HibernateUtil.openSession();
Transaction ts = session.beginTransaction();
User user = session.load(User.class, 1L);
System.out.println(111);
System.out.println(user);
System.out.println("订单数量" + user.getOrders().size());
System.out.println("订单:" + user.getOrders());
ts.commit();
session.close();
}当我们给set配置了一个true(延迟加载的时候),当访问到订单数量的时候,其实下面一句订单就不会去数据库访问,因为在获得size的时候,已经通过数据库获得了orders
下面是执行的sql语句,和结果
Hibernate:
select
orders0_.uid as uid4_1_0_,
orders0_.oid as oid1_1_0_,
orders0_.oid as oid1_1_1_,
orders0_.oprice as oprice2_1_1_,
orders0_.oname as oname3_1_1_,
orders0_.uid as uid4_1_1_
from
order1 orders0_
where
orders0_.uid=?
订单数量2
订单:[Order [oid=2, oname=货物1, oprice=12.6], Order [oid=1, oname=ww, oprice=12.0]]而当我们使用了extra(加强延迟加载),结果是这样的
Hibernate:
select
user0_.uid as uid1_6_0_,
user0_.uname as uname2_6_0_,
user0_.upwd as upwd3_6_0_
from
user user0_
where
user0_.uid=?
User [uid=1, uname=小李, upwd=2333]
Hibernate:
select
count(oid)
from
order1
where
uid =?
订单数量2
Hibernate:
select
orders0_.uid as uid4_1_0_,
orders0_.oid as oid1_1_0_,
orders0_.oid as oid1_1_1_,
orders0_.oprice as oprice2_1_1_,
orders0_.oname as oname3_1_1_,
orders0_.uid as uid4_1_1_
from
order1 orders0_
where
orders0_.uid=?
订单:[Order [oid=2, oname=货物1, oprice=12.6], Order [oid=1, oname=ww, oprice=12.0]]在查询订单数量的时候,就只是查询了个数,连订单都懒得查,,,,
现在再来说说fetch,有3种属性
join:底层使用迫切左外连接
select:使用多个select语句(默认值)
subselect:使用子查询
个人感觉就是查询方式不一样,除了join是忽略是否延迟加载,都是立即加载之外,,,感觉没什么区别
下面是set加载的组合
select true 默认值, 会在使用集合时加载,普通select语句
select false 立刻使用select语句加载集合数据
select extra 会在使用集合时加载,普通select语句,如果只是获得集合的长度,会发送Count语句查询长度.
join true 查询集合时使用表链接查询,会立刻加载集合数据
join false 查询集合时使用表链接查询,会立刻加载集合数据
join extra 查询集合时使用表链接查询,会立刻加载集合数据
subselect true 会在使用集合时加载,子查询语句
subselect false 会在查询用户时,立即使用子查询加载客户的订单数据
subselect extra 会在使用集合时加载,子查询语句,如果只是获得集合的长度,会发送Count语句查询长度.说完了一方,再接下去说说多方,多方和一方的区别在与
<many-to-one name="user" column="uid" class="model.User" cascade="save-update" lazy="xxx"></many-to-one>一方的fetch只有2种,少了subsekect,lazy取值:false、proxy、no-proxy
false:立即
proxy:采用关联对象 类级别检索的策略。lazy="proxy"是否延迟,取决关联对象 类级别检索策略。
| 检索策略 | 优点 | 缺点 |
优先考虑使用的场合 |
| 立即检索 |
对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象 |
(1)select语句多 (2)可能会加载应用程序不需要访问的对象,浪费许多内存空间。 |
(1)类级别 (2)应用程序需要立即访问的对象 (3)使用了二级缓存 |
| 延迟检索 |
由应用程序决定需要加载哪些对象,可以避免执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间 |
应用程序如果希望访问游离状态的代理类实例,必须保证她在持久化状态时已经被初始化。 |
(1)一对多或者多对多关联 (2)应用程序不需要立即访问或 |
| 表连接检索 |
(1)对应用程序完全透明,不管对象处于持久化状态还是游离状态,都可从一个对象导航到另一个对象。 (2)使用了外连接,select语句少 |
(1)可能会加载应用程序不需要访问的对象,浪费内存。 (2)复杂的数据库表连接也会影响检索性能。 |
(1)多对一或一对一关联 (2)需要立即访问的对象 (3)数据库有良好的表连接性能。 |
本文详细探讨了在Hibernate ORM框架中实现对象关联时的立即加载与延迟加载策略,包括不同配置选项及其对性能的影响。
1121

被折叠的 条评论
为什么被折叠?



