mybatis有两级缓存机制,一级缓存默认开启,可以在手动关闭;二级缓存默认关闭,可以手动开启。一级缓存为线程内缓存,二级缓存为线程间缓存。

一提缓存,必是查询。缓存的作用就是查询快。写操作只能使得缓存失效,不管是一级缓存还是二级缓存,一旦发生写操作,缓存就要清空一次。

缓存是把双刃剑,用得好比较难,用不好就把自己伤着了。

Perpetual这个单词,意为“永恒”。PerpetualCache表示永不过期的缓存。mybatis的两级缓存都是默认为PerpetualCahe,一级缓存的缓冲机制不能更改,二级缓存的缓冲定制性非常强。可以自定义存储源(存储源其实就相当于一个HashMap,把查询跟查询结果一一对应起来)。

一级缓存默认开启,它的实现为PerpetualCache,作用范围为Session,对于同一个Session,如果查询同一个事物查询两次,那么只执行一次数据库操作。它的清空条件有如下三种:

* 写操作

* 手动执行SqlSession#clearCache()

* SqlSession#close()关闭之后缓存当然要清空,所以数据库连接池不会发生Session之间共享一级缓存的情况。

二级缓存默认关闭,需要手动开启。它的作用域为mapper,是多线程之间共享的缓存,是应用级缓存,多个Session可以共用同一个mapper的缓存,每一个mapper维护一份缓存对象,但是可以配置多个mapper共用一份缓存对象,通过cache-ref标签。

二级缓存粒度十分精细:

* 全局总开关<settings>中设置cacheEnabled=true则开启二级缓存

* mapper有cache属性

* 语句的useCache=true

缓存机制使用顺序:二级缓存->一级缓存->数据库

二级缓存的选择:

* mybatis自带的缓存

* 用户自定义

* 第三方内存缓存库集成

二级缓存注意事项:

* 在数据库中一旦使用触发器,缓存里面有可能得不到相应的更新,有可能造成数据库里更新了很多,内存里面缓存浑然不知,所以触发器与缓存悠着点用,除非十分确定二者不会互相干扰。

* 对于同一个表的写操作和读操作必须定义在同一个mapper中(同一个namespace中),假如分开成读mapper和写mapper,那么写操作之后无法清空读mapper,缓存变成脏数据。

* 如果一个数据库表对应一个mapper,对一个表的写操作不能直接执行对其它表的写操作(必须经过其他表的mapper来执行写操作),否则其他表的缓存可能变成脏数据。

* csdn上一位大神说目前mybatis的缓存机制就是垃圾,根本不可用。

一级缓存测试:

在数据库中创建表test

CREATE TABLE `test` (
   `id` ) NOT NULL AUTO_INCREMENT,
   `name` ) DEFAULT NULL,
   PRIMARY KEY (`id`)
 ) ENGINE DEFAULT CHARSET=utf8mb4

插入a,b,c,d四条数据

interface H {
    @Select("select name from test")
    List<String> get();
}
public class Main {
    public static void main(String[] args) {
        SqlSession session = Util.sessionFactory.openSession();
        H h = session.getMapper(H.class);
        List<String> a = h.get();
        for (int i = 0; i < a.size(); i++) {
            a.set(i, a.get(i) + " haha");
        }
        System.out.println(a.stream().collect(Collectors.joining(",")));
        a = h.get();
        a.stream().forEach(System.out::println);
        session.close();
    }
}

第一次查询结果没有后缀’haha‘,第二次查询有后缀’haha‘。这表明第二次使用了缓存,第一次查询之后所得到的List<String>跟缓存中的List<String>是同一个对象。所以如果使用一级缓存,对查询结果不能进行修改;也可以不使用一级缓存了,禁用之,通过把localCacheScope设为语句级别的,默认为SESSION,表示session级别的。

 <setting name="localCacheScope" value="STATEMENT"/>

mybatis缓存学习笔记的更多相关文章

  1. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)——动态SQL 如果使用JDBC或者其他框架,很多时候需要你根据需求手动拼装SQL语句,这是一件非常麻烦的事情.MyBatis提供了对SQL语句动态的组装能力,而且他只有 ...

  2. MyBatis 3学习笔记

    MyBatis 3 一.MyBatis简介 优秀的持久层框架,支持支持自定义 SQL.存储过程以及高级映射,专注于SQL的编写. ​ 为什么不使用工具类进行数据库操作: ​ 功能简单,sql语句编写在 ...

  3. mybatis的学习笔记

    前几天学习了mybatis,今天来复习一下它的内容. mybatis是一个基于Java的持久层框架,那就涉及到数据库的操作.首先来提出第一个问题:java有jdbc连接数据库,我们为什么还要使用框架呢 ...

  4. 关于mybatis的学习笔记

    配置文件 贴出mybatis的配置文件,这里mybatis还未与spring做整合: <?xml version="1.0" encoding="UTF-8&quo ...

  5. memcache/redis 缓存学习笔记

    0.redis和memcache的区别 a.redis可以存储除了string之外的对象,如list,hash等 b.服务器宕机以后,redis会把内存的数据持久化到磁盘上,而memcache则不会 ...

  6. MyBatis基础学习笔记--自总结

    一.MyBatis和jdbc的区别 jdbc的过程包括: 1.加载数据库驱动. 2.建立数据库连接. 3.编写sql语句. 4.获取Statement:(Statement.PrepareStatem ...

  7. android图片的异步加载和双缓存学习笔记——DisplayImageOptions (转)

    转的地址:http://hunankeda110.iteye.com/blog/1897961 1 //设置图片在下载期间显示的图片 2 showStubImage(R.drawable.ic_lau ...

  8. 3、MyBatis.Net学习笔记之增删改

    增删改之前先说一下笔记1里提到的一个无法创建ISqlMapper对象的问题. <resultMaps> <resultMap id="FullResultMap" ...

  9. MyBatis基础学习笔记--摘录

    1.MyBatis是什么? MyBatis源自于IBatis,是一个持久层框架,封装了jdbc操作数据库的过程,使得开发者只用关心sql语句,无需关心驱动加载.连接,创建statement,手动设置参 ...

随机推荐

  1. 关于iOS构建版本提交iTunes后,一直不出现,没加号的解决方案

    最近第一次遇到,正常打包,上传iTunes App Store,都能正常upload. 也可能是因为刚升了Xcode 8 的缘故,莫名其妙的小问题... 描述如下: 如果进iTunes的活动界面,也能 ...

  2. Linux磁盘管理之设备文件详解04

    Linux一切接文件,除了普通文件和目录文件,还包括一些其它的特殊文件:块设备文件.字符设备文件.套接字文件.链接文件等.今天这里主要说一下常见的块设备文件和字符设备文件,这2类是最常见的设备文件类. ...

  3. android 动态设置Framelayout,view,imageView,Layout高度

    直接:测试可以 Framelayout.getLayoutParams().width=600;Framelayout.getLayoutParams().height=400; 如:view,ima ...

  4. 实例浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO

    一.基本概念                                                          我们通俗一点讲: Level_triggered(水平触发):当被监控的 ...

  5. Azure 删除VHD时报错:There is currently a lease on the blob and no lease ID was specified in the request

    可下载:http://clumsyleaf.com/products/cloudxplorer 然后在Accounts中新建一个Account,账号与Key,可在相应的storage Manage A ...

  6. 大话设计模式C++版——简单工厂模式

    简单工厂模式应该是所有设计模式中最简单,也最基础的一种模式,以下是一个简单的采用工厂模式写一个加减法的计算器. 1.抽象接口类——依赖倒转原则(高层和底层都要依赖于抽象,针对接口编程) class I ...

  7. nodejs模块——fs模块

    fs模块用于对系统文件及目录进行读写操作. 一.同步和异步 使用require('fs')载入fs模块,模块中所有方法都有同步和异步两种形式. 异步方法中回调函数的第一个参数总是留给异常参数(exce ...

  8. AngularJS Filters

    过滤器可以使用一个管道字符(|)添加到表达式和指令中. AngularJS 过滤器 AngularJS 过滤器可用于转换数据: 过滤器 描述 currency 格式化数字为货币格式. filter 从 ...

  9. UESTC 33 Area --凸包面积

    题意: 求一条直线分凸包两边的面积. 解法: 因为题意会说一定穿过,那么不会有直线与某条边重合的情况.我们只要找到一个直线分成的凸包即可,另一个的面积等于总面积减去那个的面积. 怎么得到分成的一个凸包 ...

  10. KSFramework配置表:扩展表格解析类型

    解析和扩展表格 配置表示例 配置表模块在编译时,把Excel转化成TSV,并根据Excel的头部信息,生成对应的代码: 比如源码库中的Test.xlsx Excel文件,两个列头,Id和Value,其 ...