Mybatis的一级缓存和二级缓存(初步理解和应用)

目录

一.缓存的概念

二.一级缓存 

应用场景(一级&含义)

开启条件(一级)

失效条件(一级)

一级缓存失效代码示例(后续二级缓存所使用的数据表一致)

三.二级缓存

应用场景(二级&含义)

开启条件(二级)

失效条件(二级)

整合第三方缓存EHCach

四.Mybatis一二级缓存开启顺序


一.缓存的概念

        缓存是存放数据的地方,即将产生的数据暂时存放到内存中。(缓存就是数据交换的缓冲区(称作Cache),是存贮数据(使用频繁的数据)的临时地方。当用户查询数据,首先在缓存中寻找,如果找到了则直接执行。如果找不到,则去数据库中查找。-大佬的解释)

二.一级缓存 

  • 应用场景(一级&含义)

       即通过同一个SqlSession查询出来的数据会被缓存,第二次查询相同的数据的时候会直接从缓存中取数据,不会再去访问数据库再获取数据。

  • 开启条件(一级)

        Mybatis的一级缓存是默认开启的。

  • 失效条件(一级)

  1.         使用不同的SqlSession
  2.         两次查询间存在对数据的增删改操作
  3.         两次查询的查询条件不一致
  4.         手动清空了缓存
  • 一级缓存失效代码示例(后续二级缓存所使用的数据表一致)

       下面以查询员工信息为例,即通过员工的id信息查询员工所有的信息(我们通过log4j实现日志功能,来查看查询语句执行的次数,即为访问数据库的次数,需要引入log4j的依赖和文件,可以直接查到)

        员工表如下:

         

        mapper.xml如下:

        我们先看看SqlSession未失效时,Sql语句的执行情况(使用同一个SqlSession获取Mapper代理对象执行方法,查询员工信息)

        

/**
     * 测试一级缓存未失效的情况
     */
    @Test
    public void CacheTestAtFirst(){
        //获取SqlSession对象(这是封装好了的方法,直接获取)
        SqlSession sqlSession1 = SqlSessionUtil.getSqlSession();
     

        //获取Mapper代理对象
        CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
        CacheMapper mapper2 = sqlSession1.getMapper(CacheMapper.class);

        //第一次查询员工信息
        List<EmpMapper> empById1 = mapper1.getEmpById(1);
        System.out.println(empById1);


        //第二次查询员工信息
        List<EmpMapper> empById2 = mapper2.getEmpById(1);
        System.out.println(empById2);

        //关闭资源
        sqlSession1.close();

    }

        运行结果如下:

        

结论:我们通过日志可以看到,我们调用了两次查询员工信息的方法,但日志显示只执行了一次Sql语句,即只访问了一次数据库,因为第二次直接从缓存里拿数据了,这就是Mybatis的一级缓存,下面我们再看看一级缓存失效的情况。

         以下为“使用不同的SqlSession".eg(测试类)

         测试代码如下:

/**
     * 测试一级缓存,Sqlsession级别-使用不同的SqlSession会导致缓存失效
     */
    @Test
    public void CacheTestByOne(){
        //获取两个SqlSession对象
        SqlSession sqlSession1 = SqlSessionUtil.getSqlSession();
        SqlSession sqlSession2 = SqlSessionUtil.getSqlSession();

        CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);

        //执行Sql
        List<EmpMapper> empById = mapper1.getEmpById(1);

        System.out.println(empById);


        CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
        //执行Sql
        List<EmpMapper> empById1 = mapper2.getEmpById(1);
        System.out.println(empById1);

        //关闭资源
        sqlSession2.close();
        sqlSession1.close();

    }

        运行结果如下:


     

结论:可以看到,使用不同的SqlSession对象后,日志显示了两次Sql查询语句,即访问了两次数据库,Mybatis的一级缓存失效了。

        以下为“手动清空了缓存”.eg

        测试代码示例如下:

    /**
     * 手动清空缓存使得一级缓存失效
     */
    @Test
    public void CacheTestByOneA(){
        SqlSession sqlSession1 = SqlSessionUtil.getSqlSession();


        CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);

        List<EmpMapper> empById = mapper1.getEmpById(1);

        System.out.println(empById);

        //清空缓存
        sqlSession1.clearCache();


        CacheMapper mapper2 = sqlSession1.getMapper(CacheMapper.class);
        List<EmpMapper> empById1 = mapper2.getEmpById(1);
        System.out.println(empById1);


        sqlSession1.close();
    }

        运行结果如下:

结论:与第一种失效的情况一致,还有两种条件也会造成Mybatis的一级缓存失效,测试过程类似, 不再一一展示。

三.二级缓存

  • 应用场景(二级&含义)

        和一级缓存的定义相似,即由同一个SqlSessionFactory创建的(不同)SqlSession对象查询的结果会被缓存。

  • 开启条件(二级)

        1.在mapper.xml文件中设置<settings>标签,默认是开启的,不需要设置

        <settings> <setting name="cacheEnabled" value="true"/> settings>

        2.在mapper.xml文件设置<cache/>标签

        

        3.查询数据所转换的实体类类型必须转换实现序列化接口

        

        4.必须在SqlSession关闭或提交后,才会开启二级缓存

        二级缓存开启成功示例:

                测试代码如下:
                

 @Test
    public void CacheTestByTwo() throws IOException {
        //1.获取核心配置文件
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

        //2.获取Builder,从同一个sqlSessionFactory中获取SqlSession对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);

        SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
        SqlSession sqlSession2 = sqlSessionFactory.openSession(true);

        CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
        CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);

        List<EmpMapper> emp1 = mapper1.getEmpById(1);
        System.out.println(emp1);

        //关闭SqlSession
        sqlSession1.close();


        List<EmpMapper> emp2 = mapper2.getEmpById(1);
        System.out.println(emp2);

        sqlSession2.close();
        sqlSession1.close();


    }

                运行结果如下:

                        

   结论:可以看到日志中只执行了一次Sql语句,即两次查询中,只访问了一次数据库(注意Mybatis的缓存查询顺序,先二级再一级,其中显示的命中率Hit Ratio也意味开启了二级缓存)

  • 失效条件(二级)

  1. 两次查询之间执行了一次增删改操作
  2. SqlSession未关闭,数据被保存在一级缓存中

整合第三方缓存EHCach

        即使用第三方缓存来代替Mybatis的二级缓存,这里不详细介绍

四.Mybatis一二级缓存开启顺序

     查询数据时,会按照以下顺序获取数据

  1.  二级缓存中是否有数据
  2. 一级缓存中是否有数据
  3. 查询数据库

理解:Mybatis的二级缓存要比一级缓存作用域大,但也存在一级缓存中有的数据,二级缓存中没有,如使用不同的SqlSession查询数据的时候,会把查询的数据放到一级缓存中(二级缓存中没有)。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值