MyBatis 缓存

缓存

MyBatis 具有缓存功能,可以将 select 语句进行缓存,下一次调用相同的 sql 语句就可以直接返回结果,减少数据库访问。MyBatis 的缓存分为一级缓存和二级缓存

一级缓存

默认情况下 MyBatis 使用一级缓存,该缓存无法关闭

缓存生命周期

一级缓存的生命周期就是从一个 sqlSession 创建到 sqlSession.close() 为止,事实上, 一级缓存就保存在 sqlSession 实例中,具体在其 localCache 字段内,以哈希表的形式保存

MyBatis 缓存

在执行 sqlSession.close() 后,localCache 就会被设为 null

缓存刷新

  1. 当执行数据库修改操作(insert,update,delete等)后,缓存会失效

    System.out.println(mapper.selectById(1));
    System.out.println(mapper.selectById(1));
    System.out.println("==================");
    
    mapper.update(new User(1,"user","3214"));
    
    System.out.println("==================");
    
    System.out.println(mapper.selectById(1));
    

    通过日志我们可以清楚地看到

    ==>  Preparing: select id,name,password from user where id=?
    ==> Parameters: 1(Integer)
    <==    Columns: id, name, password
    <==        Row: 1, user, 134
    <==      Total: 1
    User{id=1, name='user', password='134'}
    User{id=1, name='user', password='134'}                       // 直接返回缓存
    ==================
    ==>  Preparing: update user set name=?,password=? where id=?
    ==> Parameters: user(String), 3214(String), 1(Integer)
    <==    Updates: 1
    ==================
    ==>  Preparing: select id,name,password from user where id=?  // 缓存失效,重新查询
    ==> Parameters: 1(Integer)
    <==    Columns: id, name, password
    <==        Row: 1, user, 3214
    <==      Total: 1
    User{id=1, name='user', password='3214'}
    
  2. 手动清理缓存

    通过 sqlSession 的 clearCache() 方法可以手动刷新缓存

    System.out.println(mapper.selectById(1));
    sqlSession.clearCache();
    System.out.println(mapper.selectById(1));
    
    ==>  Preparing: select id,name,password from user where id=?
    ==> Parameters: 1(Integer)
    <==    Columns: id, name, password
    <==        Row: 1, user, 134
    <==      Total: 1
    User{id=1, name='user', password='134'}
    ==>  Preparing: select id,name,password from user where id=?
    ==> Parameters: 1(Integer)
    <==    Columns: id, name, password
    <==        Row: 1, user, 134
    <==      Total: 1
    User{id=1, name='user', password='134'}
    

二级缓存

一级缓存只作用于 Session 周期内,如果想要全局缓存就需要开启 MyBatis 的二级缓存

开启二级缓存很简单,只需要在想要缓存的映射语句所在的映射文件中添加一行:

<cache/>

另外,缓存结果集对应的对象需要实现 Serializable 接口,不然可能出错

cache 标签还可以添加属性以设置缓存的行为,包括:

  • eviction:清除缓存的策略,主要有 LRU(最近最少使用)和 FIFO(先进先出)等,默认为 LRU
  • flushInterval:缓存刷新间隔,默认为不设置,即只在调用语句时刷新
  • size:缓存保存的引用个数,默认为 1024
  • readOnly:只读,为 true 时缓存会返回缓存对象的相同实例,因此不能修改。为 false 时缓存会返回缓存对象的拷贝,速度较慢但是更安全,默认为 false返回对象拷贝依赖序列化,因此此时的对象必须实现 Serializable 接口,这也是上文提到不实现 Serializable 可能出错的原因,而如果 readOnly 为 true 就不一定要实现 Serializable 接口

示例:

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

参考

mybatis一级缓存二级缓存 - 寻找风口的猪 - 博客园 (cnblogs.com)

mybatis – MyBatis 3 | XML 映射器

上一篇:让linux虚拟机联网(执行yum操作是报错没有联网)


下一篇:C# SMTP发邮件不支持465端口的解决方案