3.0、Hibernate-延迟加载 1

3.0、Hibernate-延迟加载 1

        Hibernate 延迟加载 也叫 惰性加载、懒加载;

        

        使用延迟加载可以提高程序运行效率,Java 程序 与 数据库交互的频次越低,程序运行的效率就越高,所以我们应该尽量减少 Java 程序 与 数据库的交互次数,Hibernate 延迟加载 就很好的做好了这一点;

        先来说一下没有延迟加载怎么操作 -> 客户 和 订单,当我们查询客户对象时,因为有级联设置,所以会将对应的订单信息一并查询出来,这样就需要发送两条 SQL 语句,分别查询 客户信息 和 订单信息。

        延迟加载的思路是 -> 当我们查询客户的时候,如果没有访问订单数据,就只发送一条 SQL 语句来查询客户信息,如果需要访问订单数据的时候,则发送两条 SQL;

        所以延迟加载可以看做是一种优化机制,根据具体的需求,自动选择要执行的 SQL 语句数量

接下来用代码演示 一对多 - 延迟加载 ->

第一步:用之前 1.0 里面创建好的素材就好,这里先测试 一对多 所以用到的是 customer 和 order 这两个 pojo 实体类,查询 customer 对 order 进行延迟加载,在 customer.hbm.xml 映射文件中进行设置,延迟加载默认开启;将lazy属性设置为 true ,不过这个lazy默认就是开启的 ->

<!--        orders是实体类Customer中的属性名,该属性是一个Order类的集合,所以对应表 order-->
        <set name="orders" table="orders" lazy="true">
<!--            这里配置一下主外键 cid -->
            <key column="cid"></key>
<!--            消费者和订单的关系是一对多,所以这里是 one-to-many,然后给set类型加一个对象,对象类型是Order-->
            <one-to-many class="com.hkl.pojo.Order"></one-to-many>
        </set>

第二步:在 test 文件夹下创建 Test4.java 文件去查询一下 customer ->

import com.hkl.pojo.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test4 {
    public static void main(String[] args) {
        //        创建configuration
        Configuration configuration = new Configuration().configure();
//        获取sessionFactory
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        获取Session
        Session session = sessionFactory.openSession();

        Customer customer = session.get(Customer.class,42);
        System.out.println(customer);
        session.close();
    }
}

        运行之后我们会发现报了一个错误 -> StackOverflowError 栈溢出;这是因为 Customer 和 Order 两个 pojo 实体类中都有 toString() 方法而这两个方法中都相互调用了对方的一个对象 ,而在 Java 中栈的空间是有限的不断的去创建对象一定会导致栈溢出,如下->

//在 Customer.java pojo实体类中,有一个 Set 类型的集合类 Order
private Set<Order> orders;    

//在 Order.java pojo实体类中有一个Customer类型的对象 customer
private Customer customer;

解决方案 -> 将其中一个 pojo 实体类中的 toString() 方法去掉 或者 将其中一个 toString() 方法让他不要调用另一个 pojo 类的对象即可;成功查询 ->

 

这时候我们只是查询一张表 customer ,如果我们把 Test4.java 文件中的 ->

System.out.println(customer);

改为 ->

System.out.println(customer.getOrders());

可以发现有两条 SQL 语句,查询了两次 ->

        这个例子体现出了 Hibernate 延迟加载的作用,会自动的根据当前的需求来选择要查询的语句,如果你只需要查询主表的信息那么一条 SQL 语句就搞定,但是如果要把从表的数据能够带出来就会调用两条 SQL 语句;

但是如果我们把延迟加载关掉 -> lazy = "false"

<!--        orders是实体类Customer中的属性名,该属性是一个Order类的集合,所以对应表 order-->
        <set name="orders" table="orders" lazy="false">
<!--            这里配置一下主外键 cid -->
            <key column="cid"></key>
<!--            消费者和订单的关系是一对多,所以这里是 one-to-many,然后给set类型加一个对象,对象类型是Order-->
            <one-to-many class="com.hkl.pojo.Order"></one-to-many>
        </set>

再去只查询主表 customer 会发现还是有两条 SQL 语句 ->

这是因为我们把延迟加载关掉了,他就变成立刻加载了,只要查询主表就会把从表带出来~

lazy知识补充:

        这里再补充一点:lazy除了可以设置 true 和 false 之外,还可以设置 extra ,extra 是比 true 更加懒惰的一种加载方式,或者说是更加智能的一种加载方式,下面我们通过例子来演示一下 ->        

        我们测试一下 -> 先将 lazy 设置为 true 查询 Customer 对象,然后打印该对象对应的 orders 集合的长度;

        可以看到查询了两条 SQL 语句,并且打印出来 长度是 1 ;

        比如说我们有三条数据,他会先把这三条数据查询出来然后封装成三个对象,然后再把这三个对象装载到一个集合里面,之后将这个集合赋给我们的 customer,最后然后再从集合里面调用 Set;

        相当于先把对象装到集合里面然后再去判断集合的长度,这样其实是有点浪费我们资源的,因为我们只需要判断长度,我并不需要知道他具体的信息是什么;

然后将 lazy 设置为 extra,再跑一遍结果如下->

        这里我们只需要判断有几条数据就可以了,并不需要像之前那样将每条数据封装成对象,再把对象装载到集合里,再去判断集合的长度的一系列操作;

        与刚刚的语句相比较更为的方便、高效、合理;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值