hibernate 十一 延迟加载


     在hibernate应用中,有时要访问指定的持久化对象,在加载该对象时就没有必需加载其它关联对象,以免浪费内存资源,有时还需要访问其关联的对象。若想在session关闭后依然能正常访问其关联对象,在加载该对象时则需要连同关联对象一并加载。

  为了满足不同的需求。hibernate提供了3种检索策略:立即加载,延迟加载,和迫切左外链接加载。


  立即加载:  lazy=false

    表示立即加载和初始化查询方法指定的对象,即使session关闭了,依然可以正常访问,hibernate默认是true,表示延迟加载, 如果要修改为立即加载,我们必须把lazy修改为false。


 在orm映射文件中的<class>标签中设置lazy属性表示对该持久化类启用何种加载策略,在类的级别上,一般采用立即加载的策略,因为加载了持久化对象后会立即访问它。

<class name="Customer" table="customer" lazy="false">


当执行如下代码时

load默认支持延迟加载,如果lazy配置了false表示load延迟加载失效

Customer cutomer = (Customer)session.load(Customer.class,1);

向服务器发送的sql为

select* from customer where id=1 

select * from orders where customer_id=1

发送2条sql语句


当加载Customer对象时,也会连同其关联对象一起加载,如果不需要访问其关联对象,会浪费大量的内存资源。


Iiterator

Iterator iterator = session.CreateQuery("from Customer as a ").list().Iterator();//加载所有顾客

Hibernate先数据库发送的sql
select * from customer

select * from orders where customer_id=1

select * from orders where customer_id=2

select * from orders where customer_id=3

会发4条sql效率非常低,占内存。


这个时候我们可以用批量来取,在set标签中设置 batch-size="3"

这时的sql语句为

select * from customer

select * from orders where customer_id  in(1,2,3)


注意,不管在<class>标签中lazy如果设置何值,也就是说不管类别启用何种检索策略,当使用session实例的get()方法装在持久化对象时均使用立即检索。

也就是get方法不支持延迟加载。



 延迟加载  lazy=true  


hibernate默认是表示延迟加载,所以lazy默认为true

 在orm映射文件中<set>标签中设置lazy属性则表示对该持久化类的关联对象启用何种策略,在关联级别上,一般启用延迟加载策略,因为在加载了持久化对象后大多不会立即访问其关联对象,况且当关联对象数据量大时,将其装入内存开销也很大。

<set name="orders" table="selecteditems" lazy="true"
inverse="true" cascade="save-update">
<key column="itemid"></key>
<many-to-many class="com.xiu.hibernate.cascade.Orders"
column="orderid">
</many-to-many>
</set>



立即加载和延迟加载的比较(hibernate默认是延迟加载)


1. 立即加载

     配置文件

  <set name="orders" cascade="all" inverse="true" lazy="false">    lazy=false表示立即加载,默认为true


测试代码

public static void main(String[] args) {
SessionFactory sessionFactory = HibernateSessionFactory
.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Customer c = (Customer) session.load(Customer.class, 1);
tx.commit();
System.out.println(c.getBank());


}


运行结果:

Hibernate: 
    select
        customer0_.id as id0_0_,
        customer0_.cname as cname0_0_,
        customer0_.phone as phone0_0_,
        customer0_.bank as bank0_0_ 
    from
        customer customer0_ 
    where
        customer0_.id=?
Hibernate: 
    select
        orders0_.customer_id as customer4_1_,
        orders0_.id as id1_,
        orders0_.id as id4_0_,
        orders0_.orderno as orderno4_0_,
        orders0_.money as money4_0_,
        orders0_.customer_id as customer4_4_0_ 
    from
        orders orders0_ 
    where
        orders0_.customer_id=?
招商银行


该结果表示已经查询了2张表。


2。延迟加载


  只需要把lazy修改为true


测试代码一样,只是sql的过程不一样,sql只会去查询一个表

Hibernate: 
    select
        customer0_.id as id0_0_,
        customer0_.cname as cname0_0_,
        customer0_.phone as phone0_0_,
        customer0_.bank as bank0_0_ 
    from
        customer customer0_ 
    where
        customer0_.id=?
招商银行



左外链接加载


select *  from customer c LEFT OUTER JOIN orders o  on c.ID=o.CUSTOMER_ID

以上是左外链接的sql语句


左外链接加载就是充分利用sql的外链接查询功能,减少select语句的数目。

在Hibernate 中若要启用左外加载策略,只需要将所属标签的outer-join的属性设置为true即可。


1. 默认设置out-join=true


<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.xiu.hibernate.cascade">
<class name="Customer" table="customer" lazy="false"><!-- 在类的级别上设置为立即加载 -->
<id name="id" column="id" type="int">
<generator class="increment"></generator>
</id>
<property name="cname" type="string" column="cname"></property>
<property name="phone" type="string" column="phone"></property>
<property name="bank" type="string" column="bank"></property>
<set name="orders" cascade="all" inverse="false" outer-join="true"> 默认为true
inverse 若为false表示主控制方负责关联关系的维护,若为true表示
有被控制方来维护关系,默认是false
-->
<key column="customer_id"></key>
<one-to-many class="com.xiu.hibernate.cascade.Orders" />
</set>
</class>
</hibernate-mapping>

测试代码同上

运行结果:

Hibernate: 
    select
        customer0_.id as id0_1_,
        customer0_.cname as cname0_1_,
        customer0_.phone as phone0_1_,
        customer0_.bank as bank0_1_,
        orders1_.customer_id as customer4_3_,
        orders1_.id as id3_,
        orders1_.id as id4_0_,
        orders1_.orderno as orderno4_0_,
        orders1_.money as money4_0_,
        orders1_.customer_id as customer4_4_0_ 
    from
        customer customer0_ 
    left outer join
        orders orders1_ 
            on customer0_.id=orders1_.customer_id 
    where
        customer0_.id=?
招商银行


sql语句用了左外链接

注意:当使用session.createQuery("from Cusotmer as a").list()查询所有的对象时,左链接检索策略被忽略而失效,这时有lazy属性来决定。


2. 在many-to-one上设置左外链接


<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.xiu.hibernate.cascade">
<class name="Customer" table="customer" lazy="false"><!-- 在类的级别上设置为立即加载 -->
<id name="id" column="id" type="int">
<generator class="increment"></generator>
</id>
<property name="cname" type="string" column="cname"></property>
<property name="phone" type="string" column="phone"></property>
<property name="bank" type="string" column="bank"></property>
<set name="orders" cascade="all" inverse="false" outer-join="true">
<!-- cascade表示级联,他有以下取值
1. all: 表示所有操作均在关联层级上进行连锁操作
2. save-upate  表示只有save与update操作进行连锁操作
3. delete 表示只有delete操作进行连锁操作
4. all-delete-orphan 

inverse 若为false表示主控制方负责关联关系的维护,若为true表示
有被控制方来维护关系,默认是false
-->
<key column="customer_id"></key>
<one-to-many class="com.xiu.hibernate.cascade.Orders" />
</set>
</class>
</hibernate-mapping>

测试代码:查询一个对象
SessionFactory sessionFactory = HibernateSessionFactory
.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//Customer c = (Customer) session.load(Customer.class, 1);
Orders c = (Orders) session.load(Orders.class, 1);

tx.commit();
System.out.println(c.getOrderno());


运行结果:
Hibernate: 
    select
        orders0_.id as id4_1_,
        orders0_.orderno as orderno4_1_,
        orders0_.money as money4_1_,
        orders0_.customer_id as customer4_4_1_,
        customer1_.id as id0_0_,
        customer1_.cname as cname0_0_,
        customer1_.phone as phone0_0_,
        customer1_.bank as bank0_0_ 
    from
        orders orders0_ 
    inner join
        customer customer1_ 
            on orders0_.customer_id=customer1_.id 
    where
        orders0_.id=?
订单1


测试代码:查询所有对象

hibernate配置文件还是一样,


测试代码

SessionFactory sessionFactory = HibernateSessionFactory
.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//Customer c = (Customer) session.load(Customer.class, 1);
List<Orders> list = (List<Orders>) session.createQuery(
"from Orders as o").list();
for (Orders orders : list) {
System.out.println(orders.getOrderno());
System.out.println(orders.getCustomer().getCname());


}


tx.commit();


运行结果:
Hibernate: 
    select
        orders0_.id as id4_,
        orders0_.orderno as orderno4_,
        orders0_.money as money4_,
        orders0_.customer_id as customer4_4_ 
    from
        orders orders0_
Hibernate: 
    select
        customer0_.id as id0_1_,
        customer0_.cname as cname0_1_,
        customer0_.phone as phone0_1_,
        customer0_.bank as bank0_1_,
        orders1_.customer_id as customer4_3_,
        orders1_.id as id3_,
        orders1_.id as id4_0_,
        orders1_.orderno as orderno4_0_,
        orders1_.money as money4_0_,
        orders1_.customer_id as customer4_4_0_ 
    from
        customer customer0_ 
    left outer join
        orders orders1_ 
            on customer0_.id=orders1_.customer_id 
    where
        customer0_.id=?
Hibernate: 
    select
        customer0_.id as id0_1_,
        customer0_.cname as cname0_1_,
        customer0_.phone as phone0_1_,
        customer0_.bank as bank0_1_,
        orders1_.customer_id as customer4_3_,
        orders1_.id as id3_,
        orders1_.id as id4_0_,
        orders1_.orderno as orderno4_0_,
        orders1_.money as money4_0_,
        orders1_.customer_id as customer4_4_0_ 
    from
        customer customer0_ 
    left outer join
        orders orders1_ 
            on customer0_.id=orders1_.customer_id 
    where
        customer0_.id=?
订单1
小朱
订单2
小朱
定单3
小胡


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值