zoukankan      html  css  js  c++  java
  • MyBatis(六)缓存机制 之 一级缓存

    一、一级缓存介绍

      1、一级缓存(local cache),即本地缓存,作用域默认为 SqlSession。当 Session flush 或 close 后,该 session 中的所有 Cache 将被清空。

      2、本地缓存不能被关闭,但可以调用 clearCache() 来清空本地缓存,或者改变缓存的作用域。

      3、在 MyBatis3.1 之后,可以配置本地缓存的作用域,在 MyBatis.xml 中配置。

      4、一级缓存是 sqlsession 级别的缓存。一级缓存是一直开启的,sqlsession级别的一个 map,与数据库同一次会话期间查询到的数据会放在本地缓存中。

        多个一级缓存中的数据不能共用。

        以后如果需要获取相同的数据,直接从缓存中获取,不必再去查询数据库。

      5、一级缓存的工作机制

        同一次会话期间只要查询过的数据都会保存在当前的 SqlSession 的一个 Map 中

        key:hashCode+查询的 SqlId + 编写的 sql 查询语句 + 参数

    二、一级缓存失效的四种情况

      一级缓存失效情况(没有使用到当前一级缓存的情况,效果就是,还需要再向数据发送SQL)

      1、sqlSession 不同:使用不同的 sqlSession 数据库会话,不同的 SqlSession 对应不同的一级缓存;

      2、sqlSession 相同:但查询条件不同(当前一级缓存中还没有这个数据)

      3、如果sqlSession相同:两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)

      4、如果sqlSession相同,手动清除了一级缓存(把缓存内容清空)

      SqlSession 级别的缓存就相当于一个 Map。

    三、一级缓存演示

      1、在同一个 SqlSession 中查询同一条记录

        代码:

        /**
          * mybatis中的一级缓存默认开启,是SqlSession级别的
          * 即同一个SqlSession对于一个sql语句,执行之后就会存储在缓存中,
          * 下次执行相同的sql,直接从缓存中取
          */
          @Test
          public void testFirstLevelCache() throws IOException {
               SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
               SqlSession sqlSession = sqlSessionFactory.openSession();
               try {
                    EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
                    Employee emp01 = mapper.getEmpById(1);
                    System.out.println("emp01 = " + emp01);
    
                    //处理业务
                    Employee emp02 = mapper.getEmpById(1);
                    System.out.println("emp02 = " + emp02);
                    System.out.println(emp01 == emp02);
    
               } finally {
                    sqlSession.close();
               }
          }

        运行结果:

           可以看出,查询的是同一条记录,但第一次是从数据库中查询的,有 SQL 语句,第二次查询是就是从 缓存(SqlSession)中获取的。

      2、从不同的 SqlSession 中查询同一条记录

        代码:

        /**
          * 失效情况1:从不同的 SqlSession 中查询同一条记录
          * @throws IOException
          */
         @Test
         public void testFirstLevelCacheInvalid1() throws IOException {
              SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
              SqlSession sqlSession = sqlSessionFactory.openSession();
              try {
                   EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
                   Employee emp01 = mapper.getEmpById(1);
                   System.out.println("emp01 = " + emp01);
    
                   //处理业务
                   SqlSession sqlSession2 = sqlSessionFactory.openSession();
                   EmployeeMapperCache mapper2 = sqlSession2.getMapper(EmployeeMapperCache.class);
                   Employee emp02 = mapper2.getEmpById(1);
                   System.out.println("emp02 = " + emp02);
    
                   System.out.println(emp01 == emp02);
    
              } finally {
                   sqlSession.close();
              }
         }

        运行结果:

         虽然查询的是同一条记录,但是从不同的 SqlSession 中获取的,都从数据库进行查询,并没有从缓存中获取。

      3、sqlSession 相同,但查询条件不同

        代码:

        /**
          * 失效情况2:sqlSession 相同:但查询条件不同
          * @throws IOException
          */
         @Test
         public void testFirstLevelCacheInvalid2() throws IOException {
              SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
              SqlSession sqlSession = sqlSessionFactory.openSession();
              try {
                   EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
                   Employee emp01 = mapper.getEmpById(1);
                   System.out.println("emp01 = " + emp01);
    
                   //处理业务
                   Employee emp02 = mapper.getEmpById(3);
                   System.out.println("emp02 = " + emp02);
    
                   System.out.println(emp01 == emp02);
              } finally {
                   sqlSession.close();
              }
         }

        运行结果:

         使用的是同一个 sqlSession 对象,但是查询条件不同,也没有用到缓存,因为缓存中就没有符合此查询条件的数据。

      4、在通过一个 SqlSession 中,两次查询之间有 增删改操作

            代码:

        /**
          * 失效情况3:在通过一个 SqlSession 中,两次查询之间有 增删改操作
          * @throws IOException
          */
         @Test
         public void testFirstLevelCacheInvalid3() throws IOException {
              SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
              SqlSession sqlSession = sqlSessionFactory.openSession();
              try {
                   EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
                   Employee emp01 = mapper.getEmpById(1);
                   System.out.println("emp01 = " + emp01);
    
                   //处理业务
                   mapper.updateEmp(new Employee(3, "John", "1", "John@163.com"));
                   System.out.println("更新成功");
    
                   Employee emp02 = mapper.getEmpById(1);
                   System.out.println("emp02 = " + emp02);
    
                   System.out.println(emp01 == emp02);
              } finally {
                   sqlSession.close();
              }
         }

        运行结果:

       还是从同一个 SqlSession 中查询同一条记录,但由于期间涉及了增删改操作,一级缓存就会失效。

      (因为有可能修改的就是 查询的记录,这时再返回,就与数据库中记录不一致)

      5、在同一个 SqlSession 中,手动清空缓存

        代码:

        /**
          * 失效情况4:在同一个 SqlSession 中,手动清空缓存
          * @throws IOException
          */
         @Test
         public void testFirstLevelCacheInvalid4() throws IOException {
              SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
              SqlSession sqlSession = sqlSessionFactory.openSession();
              try {
                   EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
                   Employee emp01 = mapper.getEmpById(1);
                   System.out.println("emp01 = " + emp01);
    
                   //处理业务
                   sqlSession.clearCache();
    
                   Employee emp02 = mapper.getEmpById(1);
                   System.out.println("emp02 = " + emp02);
    
                   System.out.println(emp01 == emp02);
              } finally {
                   sqlSession.close();
              }
         }

        运行结果:

       虽然是在同一个 SqlSession 中进行查询的同一条记录,但由于在两次查询期间清空了缓存,还需要重新从数据库查询。

  • 相关阅读:
    软件工程 2016.6.28 日报
    软件工程课程总结
    工大助手--项目总结
    工大助手--加权平均分计算
    工大助手--数据查询
    7.5
    7月4日日报
    7.3日报
    6.30日报
    6.29.日报
  • 原文地址:https://www.cnblogs.com/niujifei/p/15243662.html
Copyright © 2011-2022 走看看