zoukankan      html  css  js  c++  java
  • hibernate笔记--缓存机制之 一级缓存(session缓存)

    一级缓存:

      又称为session缓存,它和session生命周期相同,周期非常短.是事务级别的缓存:

      还是以Book和Category这两个表为例,我们用代码观察一个缓存的存在:

    假设现在我要去查询id=1的Book信息:

            List<Book> list =(List) session.createQuery("from Book").list();
            System.out.println(list.get(0).getName());
            Book book = (Book)session.get(Book.class, 1);
            System.out.println(book.getName());        

    我这里先查询了所有的Book,打印出了index=0,即id=1的那本书的书名,接着用get方法再次获取了id=1的Book,我们看一下控制台的打印信息:

      通过打印信息我们能发现一个现象,当第二次我们使用get(..)方法去查询时,我们如愿得到了书名,但却没有select语句,说明了什么问题?说明了使用get()方法获取id=1的Book时,hibernate并没有去访问数据库,而是在某一个地方就得到了这个id=1的Book的信息,不难发现,我们第一次使用createQuery()时,其实已经得到了这条Book的信息,而hibernate将这些信息放到了一个缓存里,当执行查询语句时,hibernate没有着急的立即访问数据库去查询,而是先到这个缓存里去找找有没有他所要查询的数据,如果有的话,那就皆大欢喜了,不需要访问数据库,提高了效率,而这个缓存.就是我们所说的一级缓存,也叫session缓存.

      同时我们也能知道,get方法使用了一级缓存,用get查询数据时,首先检查缓存中是否有该数据,如果有,直接从缓存中获取该数据直接返回,如果没有,再去访问数据库查找.load也支持一级缓存,但是同时load同时也支持延迟加载.要注意.

      接下继续测试代码:

    List<Book> list =(List) session.createQuery("from Book").list();
    System.out.println(list.get(0).getName());
            
     list =(List) session.createQuery("from Book").list();
     System.out.println(list.get(0).getName())

    在代码中,我们执行了两次session.createQuery(),如果只打印一条sql语句,说明list查询也支持一级缓存,打印结果是这样:

    很不幸,控制台打印出了两条sql语句,这就说明了:

      list查询不支持一级缓存,但list查询会把返回的结果保存到session缓存,同理uniqueResult()查询也是如此.

    接下来继续测试:

    List<Book> list =(List) session.createQuery("from Book").list();
     System.out.println(list.get(0).getName());
            
     Iterator<Book> iter = session.createQuery("from Book").iterate();
      while(iter.hasNext()){
             System.out.println(iter.next().getName());
      }

    这里我们第一次使用list查询得到所有Book信息,然后用iterate查询,得到一个包含所有Book的迭代器集合,那么他会不会支持一级缓存,这是控制台打印的信息:

      乍一看,第二次查询的时候依然打出了sql语句,看来iterate查询是不会先去session中查找的了,但是仔细观察第一条sql语句,可以发现,它仅仅查询了Book的id,但依然打印出了每本书的书名.说明了,iterate依然是在缓存中查询的数据,所以,iterate是支持一级缓存的,同样它执行的查询,也会把返回结果保存到session缓存中.

    ` 现在再来看一下管理session的几个方法.

    1. session.flush():一般是结合事务对象Transaction用的,用来清理缓存,执行sql,避免内存溢出,假设你要保存十万条数据,你肯定不希望当保存到九万条的时候程序出错,然后事务回滚,导致一条数据都没有保存上,这时候你可以每保存一千条数据就执行一次session.flush(),这样的话,每保存一千条数据,就会执行到数据库,然后清理一下session缓存.
    2. session.evict(...);从session缓存中干掉你指定的某一个对象.
    3. session.clear():将当前session缓存中保存的所有对象统统干掉.

    下面用代码演示一下evict,和clear方法:

         Book book =(Book) session.get(Book.class,1);
            System.out.println(book.getName());
            session.evict(book);
            //b表示干掉session中保存的所有对象,当然也包括Book对象
            //session.clear()
            book =(Book) session.get(Book.class,1);
            System.out.println(book.getName());

    按照我们的设想,由于执行第二次查询之前,我们通过session.evict(book)方法,干掉了book对象,再次查询时会去访问数据库,来看一下控制台打印结果是不是这样的:

    果然如此,跟我们料想的一样.

  • 相关阅读:
    ActiveMQ持久化机制
    ActiveMQ的使用
    ActiveMQ解释
    Linux CentOS安装Tomcat
    nginx使用Keepalived
    Session共享解决方案
    Spring框架AOP使用扩展
    Myabtis测试(二)错题整理分析
    初识Spring及打印机案例
    MyBatis注解
  • 原文地址:https://www.cnblogs.com/fingerboy/p/5257667.html
Copyright © 2011-2022 走看看