myBatis学习笔记(8)—— 一级缓存&二级缓存

来源:互联网 发布:淘宝网账号登录历史 编辑:程序博客网 时间:2024/04/30 12:18

一级缓存

一级缓存的范围是session

  • 测试缓存
        SqlSessionFactory factory = MyBatisUtil.getFactory();        SqlSession session = factory.openSession(true);        String statement = "com.bank.userMapper.getUser";        User user = session.selectOne(statement, "Tom");        System.out.println(user);        //再次查询(查询条件相同)        user = session.selectOne(statement, "Tom");        System.out.println(user);        session.close();

这里写图片描述

在上述代码中,执行了两次查询,但是根据控制台打印出来的日志来看,实际上只查询了一次,第二次查询的结果是使用了缓存

  • 手动清除缓存
        SqlSessionFactory factory = MyBatisUtil.getFactory();        SqlSession session = factory.openSession(true);        String statement = "com.bank.userMapper.getUser";        User user = session.selectOne(statement, "Tom");        System.out.println(user);        session.clearCache();        //再次查询(查询条件相同)        user = session.selectOne(statement, "Tom");        System.out.println(user);        session.close();

这里写图片描述

在上述代码中,第二次查询之前使用了session.clearCache(); 来清除缓存,控制台结果说明了清除成功,查询语句确实调用了两次。

  • 重新获取一个session来查询
        SqlSessionFactory factory = MyBatisUtil.getFactory();        SqlSession session = factory.openSession(true);        String statement = "com.bank.userMapper.getUser";        User user = session.selectOne(statement, "Tom");        System.out.println(user);        session.close();        session = factory.openSession();        //再次查询(查询条件相同)        user = session.selectOne(statement, "Tom");        System.out.println(user);        session.close();

这里写图片描述

关闭session再获取一个新的session,结果查询还是执行了两次,并没有使用缓存。说明缓存的范围是session

  • 执行增删改操作之后
        SqlSessionFactory factory = MyBatisUtil.getFactory();        SqlSession session = factory.openSession(true);        String statement = "com.bank.userMapper.getUser";        User user = session.selectOne(statement, "Tom");        System.out.println(user);        //执行更新操作        session.update("com.bank.userMapper.updateUser", new User("Tom", 111));        System.out.println("执行了更新操作=================");        //再次查询(查询条件相同)        user = session.selectOne(statement, "Tom");        System.out.println(user);        session.close();

这里写图片描述

结果说明:执行了增删改操作之后,缓存将被清除

二级缓存

二级缓存的范围是映射文件(mapper)

  • 开启二级缓存

    • 在映射文件中,加上<cache></cache>
    • 序列化实体类public class User implements Serializable{...}
  • 测试二级缓存

        SqlSessionFactory factory = MyBatisUtil.getFactory();        //创建两个session        SqlSession session = factory.openSession();        SqlSession session2 = factory.openSession();        String statement = "com.bank.userMapper.getUser";        User user = session.selectOne(statement, "Tom");        System.out.println(user);        //必须提交才会使用二级缓存        session.commit();        //再次查询        user = session2.selectOne(statement, "Tom");        System.out.println(user);

这里写图片描述

截图证明的确使用了缓存,而且不是一级缓存,而是二级缓存。同时说明了二级缓存的范围是映射文件,不是session

  • <cache></cache> 的属性

以下内容摘自mybatis文档中文版

MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3
中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。
默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环
依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:

字面上看就是这样。这个简单语句的效果如下:
- 映射语句文件中的所有 select 语句将会被缓存。
- 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
- 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
- 根据时间表(比如 no Flush Interval,没有刷新间隔) ,缓存不会以任何时间顺序
来刷新。
- 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
- 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而
且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
所有的这些属性都可以通过缓存元素的属性来修改。比如:
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的
512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会
导致冲突。
可用的收回策略有:
- LRU – 最近最少使用的:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
- WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒
形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的
可用内存资源数目。默认值是 1024。
readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓
存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存
会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。

0 0
原创粉丝点击