mybatis的缓存机制

一级缓存

Mybatis存在一级缓存和二级缓存,默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存(一级缓存无法关闭,只能调整)

public static void main(String[] args) throws InterruptedException {
    try (SqlSession sqlSession = MybatisUtil.getSession(true)){
        TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
        Student student1 = testMapper.getStudentBySid(1);
        Student student2 = testMapper.getStudentBySid(1);
        System.out.println(student1 == student2);
    }
}

两次得到的是同一个Student对象,也就是说我们第二次查询并没有重新去构造对象,而是直接得到之前创建好的对象

public static void main(String[] args) throws InterruptedException {
    try (SqlSession sqlSession = MybatisUtil.getSession(true)){
        TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
        Student student1 = testMapper.getStudentBySid(1);
        testMapper.addStudent(new Student().setName("小李").setSex("男"));
        Student student2 = testMapper.getStudentBySid(1);
        System.out.println(student1 == student2);
    }
}

一级缓存,在进行DML操作后,会使得缓存失效,也就是说Mybatis知道我们对数据库里面的数据进行了修改,所以之前缓存的内容可能就不是当前数据库里面最新的内容了。还有一种情况就是,当前会话结束后,也会清理全部的缓存,因为已经不会再用到了。但是一定注意,一级缓存只针对于单个会话,多个会话之间不相通。

注意:一个会话DML操作只会重置当前会话的缓存,不会重置其他会话的缓存,也就是说,其他会话缓存是不会更新的!

二级缓存

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

一级缓存给我们提供了很高速的访问效率,但是它的作用范围实在是有限,如果一个会话结束,那么之前的缓存就全部失效了,但是我们希望缓存能够扩展到所有会话都能使用,因此我们可以通过二级缓存来实现,二级缓存默认是关闭状态,要开启二级缓存,我们需要在映射器XML文件中添加

<mapper namespace="edu.test.mapper.TestMapper">
    <cache
            eviction="FIFO"
            flushInterval="60000"
            size="512"
            readOnly="true"/>
    <resultMap id="test" type="Student">
    <result property="name" column="sname"/>
    <result column="sno" property="sno"/>
    <result column="sdept" property="dept"/>
    <result property="sex" column="ssex"/>
    </resultMap>


    <select id="selectMaleStudent" resultMap="test">
        select * from student where ssex='男';
    </select>

   
</mapper>

实例

    public static void main(String[] args) {
        try (SqlSession sqlSession = MybatisUtil.getSqlSession(true)) {
            SqlSession sqlSession1=MybatisUtil.getSqlSession(true);
            TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
            TestMapper testMapper1 = sqlSession1.getMapper(TestMapper.class);

            Student student1 = testMapper1.getStudent("20200512039");

            sqlSession1.close();
            Student student = testMapper.getStudent("20200512039");

            System.out.println(student == student1);
            System.out.println(student.equals(student1));
           
       }
    }

输出

开始构造
true
true

上面的代码中首先是第一个会话在进行读操作,完成后会结束会话,而第二个操作重新创建了一个新的会话,再次执行了同样的查询,我们发现得到的依然是缓存的结果。

总结:二级缓存是Mapper级别的,也就是说,当一个会话结束时,它的缓存依然会存在于二级缓存中,因此如果我们再次创建一个新的会话会直接使用之前的缓存。当第一个对话没有结束时,它的一级缓存就不会写入二级缓存中,也就是说,此时第二次对话就无法访问到之前的缓存

例子

  public static void main(String[] args) {
        try (SqlSession sqlSession = MybatisUtil.getSqlSession(true)) {
            SqlSession sqlSession1=MybatisUtil.getSqlSession(true);
            TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
            TestMapper testMapper1 = sqlSession1.getMapper(TestMapper.class);
            Student student1 = testMapper1.getStudent("20200512039");
            Student student = testMapper.getStudent("20200512039");
            System.out.println(student == student1);
            sqlSession1.close();
        }
    }

输出

开始构造
开始构造
false

添加了二级缓存之后,会先从二级缓存中查找数据,当二级缓存中没有时,才会从一级缓存中获取,当一级缓存中都还没有数据时,才会请求数据库

读取顺序:二级缓存 => 一级缓存 => 数据库

使用useCache属性来关闭缓存使用flushCache="false"在每次执行后都清空缓存,通过这这个我们还可以控制DML操作完成之后不清空缓存。

<select id="getStudentBySid" resultType="Student" useCache="false" flushCache="true">
    select * from student where sid = #{sid}
</select>

关闭Mybatis的二级缓存

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值