• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
风吹花落泪如雨
博客园    首页    新随笔    联系   管理    订阅  订阅

Hibernate学习笔记整理(七)-----Hibernate检索策略(类级别,关联级别)详解

一、概述

    检索策略分三大块,类级别检索策略和关联级别检测策略。

        类级别检索策略:get、load、

        关联级别检索策略:order.getCustomer().getName()

        上面这两种应该是看得懂的。很容易去理解,现在就具体来说说这两种其中的细节。

    批量检索解决n+1问题。

二、类级别检索策略

    2.1、立即检索  get

        直接发送sql语句,到数据库中去查询数据。

Staff staff = (Staff)session.get(Staff.class, 3);//执行完这句,就会发送sql语句,到数据库表中查询相应的数据加入一级缓存中

//结果
Hibernate: 
    select
        staff0_.id as id1_0_,
        staff0_.name as name1_0_,
        staff0_.deptId as deptId1_0_ 
    from
        staff staff0_ 
    where
        staff0_.id=?

    2.2、延迟检索  load

        不会直接发送sql语句,而是等到用的时候在发送sql语句,如果一直没用,就永远不会发送sql语句。

Staff staff = (Staff)session.load(Staff.class, 3);//执行完这句,不会发送sql语句
        System.out.println("load后还没发送sql语句,等用到的时候才会发送。");
        System.out.println(staff.getName());//现在需要用staff。则会发送sql语句。

//结果

load后还没发送sql语句,等用到的时候才会发送。
Hibernate: 
    select
        staff0_.id as id1_0_,
        staff0_.name as name1_0_,
        staff0_.deptId as deptId1_0_ 
    from
        staff staff0_ 
    where
        staff0_.id=?
qqq2

    2.3、深入讲解get和load

        上面两个只是简单讲解一下立即加载和延迟加载两个概念。现在来讲点深入的东西。

      1、load检索返回的代理对象,而不是一个pojo对象,get返回的是pojo对象,这个的前提是一级缓存中没有我们要查询的对象。

      2、get和load都是先从一级缓存中拿数据,而不是每次都从数据库中拿,也就是说如果一级缓存有我们需要的数据,就不会在发送sql语句了。并且返回就是一级缓存对象中对象的状态,也就是说如果在一级缓存中该对象的状态是pojo对象,那么就算是用load加载的,返回的也就是pojo对象,如果该对象是代理对象,那么就算get加载的,返回的也就是代理对象,不过会将代理对象的数据初始化。也就是会向数据库中发送sql语句查询数据。           解释:代理对象数据初始化:代理对象中包含了我们想要的pojo对象的所有信息。

        例子:一级缓存中的是代理对象,使用get获得

Staff staff = (Staff)session.load(Staff.class, 3);//staff代理对象加入缓存中了
        System.out.println("没有发送sql语句,get之后就会发送。");
        Staff staff1 = (Staff)session.get(Staff.class, 3);//get获取了缓存中的代理对象,并且初始化

//结果
没有发送sql语句,get之后就会发送。
Hibernate: 
    select
        staff0_.id as id1_0_,
        staff0_.name as name1_0_,
        staff0_.deptId as deptId1_0_ 
    from
        staff staff0_ 
    where
        staff0_.id=?

        例子: 一级缓存中是pojo对象,通过load获得

Staff staff = (Staff)session.get(Staff.class, 3);//staff pojo对象加入缓存中了
        System.out.println("get后发送sql语句,并且该pojo对象在一级缓存中了。");
        Staff staff1 = (Staff)session.load(Staff.class, 3);//load获取了缓存中的pojo对象

//结果
Hibernate: 
    select
        staff0_.id as id1_0_,
        staff0_.name as name1_0_,
        staff0_.deptId as deptId1_0_ 
    from
        staff staff0_ 
    where
        staff0_.id=?
get后发送sql语句,并且该pojo对象在一级缓存中了。

      3、只有在使用时,代理对象才会初始化,其实还有一种方式可以不使用代理对象而初始化数据,

因为没有初始化代理对象,在关闭session后,在使用staff1,就会报错,报错内容为不能够初始化代码对象,没有session

使用Hibernate.initialize(proxy);来对代理对象进行初始化,这个的效果和使用代理对象是一样的,但是会使代码看起来更好,如果你在这里system.out.println(代理对象),也有也可以,但是看起来总觉得乖乖的,所以hibernate就有了这个方法来对代理对象进行初始化。

      4、可以通过lazy属性来设置让load不延迟加载,而跟get一样立即加载,因为是类级别检索,所以在hbm映射文件中的class位置进行属性设置。

在staff.hbm.xml中设置了lazy=false。意思是让其延迟加载失效,所以在对staff进行查询时,使用load也是立即检索

      5、我们常说的,get如果查询数据库中没有的记录的话,返回是null,而load将会报错。这句话是正确的,但是概念很模糊,来看下面的路子看会不会报错。

          例子一:查询数据库中没有的数据,id=100,load的时候会不会报错?  不报错           

              

          例子二:查询数据库中没有的数据,id=100,并且将其取出id  不报错

              

          例子三:查询数据库中没有的数据,id=100,并且取出name  报错

              

            总结load:load加载返回的是一个代理对象,并且我们说的用load查询一个数据库中没有的数据,并不是load这条语句报异常,而是在使用时,代理对象在数据库表中找不到数据而报的异常,所以单纯只写load语句,是不会报错的,并且代理对象的id是我们手动输入进去的,不用往数据库中查也知道,所以在代理对象.getId()时也不会发送sql语句,而是拿到我们一开始的id值。

    2.4、load和get的区别(面试题)

            1、get是立即加载、load是延迟加载

            2、get和load都是先从缓存中查找对象,如果有该对象的缓存,则不向数据库中查询,并且返回的是缓存中对象的状态(是代理对象就返回代理对象,是pojo对象就返回pojo对象)

            3、在缓存中没有对象时,get返回的是pojo对象,load返回的是代理对象

 三、关联级别检索策略

关联对象属性的抓取策略(关联的表的字段)

fetch=FetchType.EAGER立即抓取(显式)   

fetch=FetchType.LAZY延迟抓取(默认)

Hibernate为了性能默认关联对象属性LAZY延迟抓取(推荐),然后在Dao层根据需要使用左外连接,内连接加上fetch关键字实现关联数据的抓取(填充)。

Query query =  session.createQuery("from Company c left join fetch c.flights where c.companyName like ?");

flights 为Company 对象的集合属性。查询结束后得到Company 关联的flights 集合数据填充到Company 对象。

 

  

posted @ 2018-03-27 23:36  风吹花落泪如雨  阅读(255)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3