前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【MyBatis框架点滴】——MyBatis二级缓存

【MyBatis框架点滴】——MyBatis二级缓存

作者头像
DannyHoo
发布2018-09-13 12:39:30
2920
发布2018-09-13 12:39:30
举报
文章被收录于专栏:Danny的专栏Danny的专栏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1337151

  在上篇文章的那张图上稍作修改,就可以很明了的看出来什么是二级缓存,它和一级缓存的区别是什么:

  一级缓存是SqlSession级别的缓存,二级缓存则是Mapper级别的缓存,这里的Mapper可以看做是Mapper配置文件。多个SqlSession可以操作同一个Mapper配置文件,所以二级缓存比一级缓存的范围要大,它是跨SqlSession的,多个SqlSession可以共享二级缓存中的数据。

开启二级缓存


  MyBatis默认不开启二级缓存,需要在两个地方手动开启:

  1、在MyBatis全局配置文件(SqlMapConfig.xml)中添加如下配置:

代码语言:javascript
复制
<configuration>
    <settings>
        <!-- 开启二级缓存 -->
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

  2、在相应Mapper配置文件下添加<cache/>

代码语言:javascript
复制
<mapper namespace="com.danny.mybatis.generator.mapper.UserMapper" >
    <!-- 开启本Mapper下的二级缓存 -->
    <cache/>
</mapper>   

  因为二级缓存的存储介质多种多样,不一定是内存,所以还需要让相应的pojo对象实现序列化接口Serializable。

  这时就可以使用二级缓存了。

二级缓存应用


实验一

代码语言:javascript
复制
@Test
    public void testCache2() throws Exception {
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        //创建代理对象
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

        // 查询id为1的用户
        User user1 = userMapper1.selectByPrimaryKey(6);
        System.out.println(user1.getUsername());
        sqlSession1.close();

        // 查询id为1的用户
        User user2 = userMapper2.selectByPrimaryKey(6);
        System.out.println(user2.getUsername());        
        sqlSession2.close();            
    }

  日志:

  由日志可以看出,第一次查询的缓存命中率为0,表示至今为止共执行了1次查询,从缓存中查出数据的次数为0;第二次的缓存命中率为05,表示至今为止共执行了2次查询,从缓存中查出数据的次数为1。

  并且不同的SqlSession查询相同的数据,只有第一次查询执行了sql语句,第二次查询直接从二级缓存中读取。(注意,执行第一次查询后,必须关闭sqlSession,才能将sqlSession中的数据写入到二级缓存区域,如果不关闭,则无法写入二级缓存)

实验二

代码语言:javascript
复制
@Test
public void testCache2() {
    SqlSession sqlSession1 = sqlSessionFactory.openSession();
    SqlSession sqlSession2 = sqlSessionFactory.openSession();
    SqlSession sqlSession3 = sqlSessionFactory.openSession();
    //创建代理对象
    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
    UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);

    // 查询id为1的用户
    User user1 = userMapper1.selectByPrimaryKey(6);
    System.out.println(user1.getUsername());
    sqlSession1.close();

    // 更新id为1的用户
    user1.setUsername("DannyHoo");
    userMapper3.updateByPrimaryKey(user1);
    sqlSession3.commit();
    sqlSession3.close();

    // 查询id为1的用户
    User user2 = userMapper2.selectByPrimaryKey(6);
    System.out.println(user2.getUsername());
    sqlSession2.close();
}

  日志:

  上面日志中看到,第一次查询的缓存命中率为0;由于sqlSession2在第二次查询之前,sqlSession3执行了改变数据库数据的操作,所以会清空该Mapper下二级缓存中的内容,导致第二次查询的缓存命中率也为0。

  两次实验的结果也可以用下面一张图来表示如下:

扩展


  1、禁用二级缓存

  在Mapper配置文件的<select>标签内添加useCache="false" 属性,可以设置该查询结果不会放到二级缓存中,每次执行该查询都会执行sql语句。

代码语言:javascript
复制
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" useCache="false">
    select 
    <include refid="Base_Column_List" />
    from user
    where id = #{id,jdbcType=INTEGER}
</select>

  这种情况比较适合对刷新频率较高的数据的查询。

  2、刷新缓存配置

  从上面可以看出,在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

  设置Mapper中statement的flushCache属性,可以设置缓存是否刷新。默认情况下为true,即执行了增删改之后会刷新二级缓存;为false时则不会刷新。(使用缓存时如果手动修改数据库表中的查询数据会出现脏读哦。)

代码语言:javascript
复制
<update id="updateByPrimaryKeySelective" parameterType="com.danny.mybatis.generator.pojo.User" flushCache="true">
……
</update>

总结:


  一般情况下,每一个Mapper文件都会设置一个namespace,如果两个Mapper文件的namespace一样的话,那么这两个Mapper其实对应同一个二级缓存区域(这两个Mapper执行的sql查询到的数据将存储在同一个二级缓存区域中),由此看来,二级缓存区域是按照Mapper的namespace来分的。


【 转载请注明出处——胡玉洋《 【MyBatis框架点滴】——MyBatis二级缓存》】

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年06月27日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档