• 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()加载

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

  • 相关阅读:
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(2)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(9)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(10)
    CKEditor在asp.net环境下的使用一例
    《Microsoft Sql server 2008 Internals》读书笔记第五章Table(7)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(11)
    千万数据的连续ID表,快速读取其中指定的某1000条数据?
    javascript中的float运算精度
    .Net与Java的互操作(.NET StockTrader微软官方示例应用程序)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(6)
  • 原文地址:https://www.cnblogs.com/wl0000-03/p/6294095.html
Copyright © 2020-2023  润新知