hibernate的加载策略

本文详细探讨了在Hibernate ORM框架中实现对象关联时的立即加载与延迟加载策略,包括不同配置选项及其对性能的影响。

当我们需要从数据库取一个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)数据库有良好的表连接性能。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值