• Hibernate 一对多,多对多,多对一检索策略


    一.概述

        我们先来谈谈检索数据时的两个问题:

         1.不浪费内存   2.更好的检索效率

         以上说的问题都是我们想要避免的,接下来就引出了我们要讨论的话题---------------hibernate检索策略

    二.hibernate检索策略分为三种:

         1.类级别的检索策略

         2.一对多和多对多检索策略

         3.多对一和一对一关联的检索策略

      (1)类级别的检索策略分为立即检索和延迟检索,默认为延迟检索。

             立即检索:立即加载检索方法指定的对象,立即发送SQL.

             延迟检索:延迟加载检索方法指定的对象,在使用具体的对象时,再进行加载,发送SQL.

       lazy有两个取值:false(立即加载) 和 true(延迟加载)

      讨论一:当用get()方法检索数据时,在类级别检索策略不管是不是延迟加载都会立即检索

      接下来看看代码实现是不是跟我说的一样:

      配置文件中:

     

    测试类代码:

     @Test
        public void select1(){
            Session session = HibernateUtil.currentSession();
            Transaction tx = session.beginTransaction();
            House house = session.get(House.class, 1);
            System.out.println("===========================");
           // System.out.println(house.getType().getName());
            tx.commit();
            HibernateUtil.closeSession();
        }

      接下来看看测试的效果:

     

    接下来我们把lazy设为true:

    效果:

    大家注意没,测试类有一行代码我是注释掉的,为的就是让我们很好的理解,如果我把下面的代码放开是什么效果呢?大家要注意现在我们的查询是get()方法:

    我们得到的结果是一样的,这样就说明了当使用类级别检索时,使用get()方法都会立即加载。

    讨论二:我们在来看看load()方法(也是类级别的检索),我们只需要修改代码即可:

       @Test
        public void select1(){
            Session session = HibernateUtil.currentSession();
            Transaction tx = session.beginTransaction();
            House house = session.load(House.class, 1);
            System.out.println("=========lazy:false==================");
            //System.out.println(house.getType().getName());
            tx.commit();
            HibernateUtil.closeSession();
        }

    lazy:false时

    我们把lazy设为true时效果如下:

    我们看到只打印了分割线,到这里我们可以看出get()和load()方法在类级别检索时的区别,接下来我们看看当放开注释的代码时会发生什么呢?

    我们可以很直观的看出来,得到的结果不一样,当延迟加载的情况下,当我们有后续操作时才会向数据库发送SQL,查询结果。而立即加载在我们有后续操作之前,已经先查询了一道,然后再根据后续操作查询结果。

    通过以上我们做的测试,我们可以得出一个结论:

    当类级别检索时:get()方法不管延迟加载还是延迟加载都会先查询一道,有后续操作再向数据库发送SQL,得到结果。

                           load()方法:当是延迟加载的情况下,有后续操作才会向数据库发送SQL,查询结果。

                                            当是立即加载的情况下,就和get()方法一样,先查询一道,有后续从操作在查询。

    总的来说,load()方法受类级别检索策略影响,get()方法不受影响。

      (2)一对多和多对多检索策略

     在映射文件中,用<set>元素来配置一对多和多对多关联关系

    lazy取值有:false(立即加载),true(延迟加载)和extra(加强延迟加载)

    配置文件:

    测试类代码:

     @Test
        public void select(){
            Session session = HibernateUtil.currentSession();
            Transaction tx = session.beginTransaction();
            House house = session.load(House.class, 1);
            System.out.println("==========lazy:false===================");
            System.out.println(house.getClass());
           // System.out.println(house.getTitle());
            tx.commit();
            HibernateUtil.closeSession();
        }

     先来看看当我们使用load()加载数据时,我们输出的结果:

    当lazy取值为false:

    当lazy取值为true:

    都没有后续操作时,没有不同。接下来我们看一下当有后续操作时(解开注释的代码),会发生什么?

    lazy:true时:

    lazy为false时: 

     

     我们可以明显的看出这两个的不同,延迟加载时发送了一条SQL,立即加载时发送了两条SQL,延迟加载的后续操作是根据你的条件查询的,立即加载根据你的条件查询之后,如果有与之相关的表,也会进行两表查询。

    get()方法获取时,没有后续操作:

    lazy:true

    lazy:false:

     

    当有后续操作时,看看是什么情况?

    lazy:true时,

    lazy:false时,

    由此可以看出,当使用get()方法时,不管有没有后续操作,都会先向数据库发送SQL语句,保存对象的信息,而且我们也看出来不管load()和get()在立即加载情况下,会向数据库发送SQL,根据你查询对象所关联的表的个数来决定向数据库发送几条SQL语句,(我列举的例子是发送两条)。

    当lazy取值为extra(加强延迟加载),接下来的测试,我们主要探讨的是获取集合的size()时有什么不同:

    配置文件:

    测试类代码:

     @Test
        public void select(){
            Session session = HibernateUtil.currentSession();
            Transaction tx = session.beginTransaction();
            Users users = session.get(Users.class, 2);
            System.out.println("==========lazy:true===================");
            System.out.println(users.getClass());
            //System.out.println(users.getHouse().size());
            tx.commit();
            HibernateUtil.closeSession();
        }

    先来探讨没有后续操作时,get()和load()方法

    get()方法:

    load()方法:

    当有后续操作时,get()和load()方法的结果:

    get()方法:

    load()方法:

    当有后续操作时,get()和load()方法向数据库索要数据的语句相同。不同的是get()方法不管有没有后续操作都会向数据库发送SQL,

    而load()方法是在你用到它的属性的时候才会向数据库发送SQL。

    最后看一下当取值为true 和 false时语句有什么不同?

    在延迟加载的情况下:

    get()方法获取数据                                             load()方法获取数据

     

    在立即加载的情况下:

    get()方法加载数据:                                                 load()方法加载数据:

    这里写的可能有点啰嗦了,但是总的一句话:

    Extra:极其懒惰,只有访问集合对象的属性时才会加载,访问集合本身的属性时(例如,集合大小,生成count),不会立即加载。

    最后来给大家总结一下:

     类级别检索策略:仅仅适用于load()加载

    好了,就讨论到这里吧,可能我写的也不是太好,这就需要自己下来多多练习,熟练实践.......

  • 相关阅读:
    git爬坑不完全指北(二):failed to push some refs to ‘XXX’的解决方案
    javascript精雕细琢(三):作用域与作用域链
    javascript精雕细琢(二):++、--那点事
    git爬坑不完全指北(一):Permission to xxx.git denied to user的解决方案
    深入浅出CSS(三):隐藏BOSS大盘点之默认属性小总结
    读书笔记
    MPP5运维手册
    HTML自闭合(self-closing)标签
    Mysql JDBC的通信协议(报文的格式和基本类型)
    详解 & 0xff 的作用
  • 原文地址:https://www.cnblogs.com/wl0000-03/p/6294095.html
Copyright © 2020-2023  润新知