一,引言

首先我们要明白一点,缓存所做的一切都是为了提高性能。明白了这一点下面我们开始进入正题。

二,mybatis缓存概要

①、mybatis的缓存有两种,分别是一级缓存和二级缓存。两者都属于查询缓存,也就是只有执行查询操作的时候才起缓存作用,对于增删改操作无效。

②、一级缓存默认开启,二级缓存默认关闭。

③、两者都可以使用SqlSession对象的commit()方法更新缓存。(你肯定是对数据修改才会commit,而数据修改了,则缓存必然要更新,否则会发生类似"脏读"的现象)。

④、二级缓存分为mybatis自带的与第三方提供的两种。三方提供的比较常用的是ehcache。

⑤、二级缓存不同于一级缓存,前者是序列化操作,也就是说二级缓存是存放在硬盘中的。而一级缓存是存放在内存中的。

下面开始详细介绍一二级缓存。

三,一级缓存

mybatis的一级缓存是默认开启的,它将数据存放在同一个SqlSession对象中。该对象可以粗略的将其理解为"封装好的数据库连接"。

当我们进行查询操作时,比如:select * from person where name ="张三"

mybatis会先检查SqlSession对象中是否存在,如果存在,则直接在缓存中获取;否则将从数据库中查找,并将找到的值缓存到SqlSession对象中。

由于此处我还未讲述二级缓存,因此先暂时忽略二级缓存的情况,在下文中我会介绍一二级缓存同时使用的情况。

 Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();

更新一级缓存:当我们执行SqlSession对象的commit()时,SqlSession对象中的缓存数据会更新。session.commit();但是由于一级缓存是在内存,不需要序列化,因此它是自动更新的,无需我们手动commit()更新缓存。二级缓存则不然,下文会有介绍。

四,mybatis二级缓存

mybatis的二级缓存是默认关闭的,如果想要使用二级缓存,我们需要在mybatis-config.xml文件中手动配置开启。

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

开启二级缓存之后我们还需要在对应的映射文件中加入<cache/>节点声明该映射文件使用二级缓存。比如我想要对peronMapper.xml使用,则在该文件中加上<cache/>节点。

与一级缓存不同的是,二级缓存的数据缓存在同一个namespace生成的映射对象中。

请牢记这句话,同一个namespace。

 //就算使用不同的SqlSession对象,只要该对象是同一个mapper映射对象,则它们共享同一个二级缓存
PersonMapper p1 = session1.getMapper(PersonMapper.class);
PersonMapper p2 = session2.getMapper(PersonMapper.class);
//p1和p2无法共享一级缓存,但可以共享二级缓存

又由于二级缓存是序列化操作,缓存存放在外存,因此涉及到的实体类需要实现序列化接口serializable。

 public class Person implements Serializable{//序列化接口
private int id;
private String name;
private int age;
...........
}

其次,因为序列化操作的I/O开关比较频繁的话会严重影响性能,所以mybatis让我们手动序列化缓存(也就是有内存输出到外存),而不是你每次查询之后,它自动帮你将缓存序列化出去。

因此我们需要使用SqlSession对象的close()方法手动序列化。close()方法类似于关闭连接。

session.close();//手动序列化二级缓存

如果你不手动序列化,则二级缓存是不会生效的哦。(二级缓存存在于外存,如果你不序列化,则仍然停留在内存中,其他的查询在外存中无法找到,因此无法生效)。

更新二级缓存:①与一级缓存类似,可以使用commit()方法手动更新二级缓存。②如果仔细阅读了上文,你其实不难发现,session.close()操作也是更新二级缓存的操作。

禁用二级缓存:由于<cache/>节点开启了整个mapper文件的二级缓存能力,而可能会有某些sql节点可能不需要用到二级缓存,这是就会造成浪费,此时我们可以使用useCache="false"属性来关闭该sql节点的二级缓存能力。

五,总结

一二级缓存已经初步讲完了,我们将一个一二级缓存同时工作的具体流程来作为总结。

现在当我们执行一个查询操作时:select *from person where name ="张三"

会先在SqlSession对象中检查是否存在着上次执行同一个sql,已经缓存好的数据(一级缓存),如果存在则直接获取。如果不存在,则再检查同一个namespace产生的mapper对象中是否存在,如果存在,则直接获取。否则将会在数据库中查找。然后将其缓存如SqlSession对象中,和其同一个namespace产生的mapper对象中。需要注意的是,此时二级缓存还没有序列化到外存中,只是在该对象中缓冲起来了,需要你手动调用close()或commit()方法手动序列化到外存中。

六,第三方缓存

上文提到过,mybatis的二级缓存分为它自带的与第三方公司提供的两种。(mybatis毕竟不是专业做缓存的,有一些专门研究缓存的公司)。

常见的三方缓存有ehcache、memcache。如果想要使用三方缓存、或自定义缓存,则必须实现mybatis提供的Cache接口(这是必然的,接口是规范)。该接口有很多实现类,默认使用的实现类是PerpetualCache。

在这里我们以ehcache为例来对三方二级缓存进行讲解。

首先需要知道,第三方,第三方,既然是第三方那么肯定需要额外导入jar包。

因此整合ehcache二级缓存需要用到的jar包有:ehcache.jar、mybatis-ehcache.jar、slf4j-api.jar(日志jar,ehcache内置的日志不是log4j)

其次,我们需要编写第三方缓存的配置文件,比如这里的ehcache缓存配置文件。其文件名约定为Ehcache.xml

配置文件的内容如下:

 <!-- 当二级缓存的数据(对象)超过内存限制(maxElementsInMemory最大的缓存对象个数)时,就要存入硬盘 -->
<diskStore path="D:\dev\ehcache repository"/>
<!--
maxElementsInMemory:设置在内存中缓存对象的最大值
maxElementsOnDisk:设置在硬盘中缓存对象的最大值
eternal:设置缓存是否永远不过期
overflowToDisk:设置当内存满了是否往硬盘中转移
timeToIdleSeconds:当2次访问超过该值(秒)的时候,缓存对象失效
timeToLiveSeconds:缓存对象的生存时间(秒)和timeToIdleSeconds差不多
diskExpiryThreadIntervalSeconds:每经过多长时间(s)就开启一个线程将硬盘中的缓存清除
memoryStoreEvictionPolicy:当超过缓存对象的最大限制时,采取的策略(删除最后面的或删除最前面的等等)。
LRU是操作系统中内存管理的一个算法,意思是Least recently used,最近最少使用。
FIFO:队列,先进先出
LFU:最不常使用
-->
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="1000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="100"
timeToLiveSeconds="100"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>

然后开启二级缓存,与上文中的步骤一样,先在mybatis-config.xml配置文件中开启,再通过具体的<cache/>节点指定相应的mapper文件启用。

与mybatis内置二级缓存不同的是,三方二级缓存需要使用type属性指明实现类(java是面向对象的语言,一切的功能都是基于类来实现的)。

语法如下:

 <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

此条配置声明了使用EhcacheCache类,该类就是ehcache二级缓存的具体实现,点进去也能够发现该类是org.apache.ibatis.cache.Cache接口的实现类。

我们也可以覆盖Ehcache.xml中的配置项,比如我如果要覆盖内存中缓存对象的最大值,则:

 <cache>
<property name="maxElementsInMemory" value="1000"/>
</cache>

三方二级缓存和内置二级缓存一样,数据缓存在【同一个namespace】生成的mapper对象中。

也是commit或close更新缓存。

也是useCache="false"禁用缓存。

也会序列化到硬盘,也要实现serializable接口。只不过三方二级缓存是先存入内存,内存存不下了再存入硬盘(可以设置不存入硬盘)。

mybatis缓存,包含一级缓存与二级缓存,包括ehcache二级缓存的更多相关文章

  1. MyBatis加强(1)~缓存机制(一级缓存、二级缓存、第三方缓存技术redis、ehcache)

    一.缓存机制 使用缓存可以使应用更快地获取数据,避免频繁的数据库交互操作,尤其是在查询越多,缓存命中率越高 的情况下,缓存的作用就越明显. 1.缓存原理:Map ■ 查询时,先从缓存区查询:找到,返回 ...

  2. MyBatis 延迟加载,一级缓存,二级缓存设置

    什么是延迟加载 resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息 ...

  3. 八 mybatis查询缓存(一级缓存,二级缓存)和ehcache整合

    1       查询缓存 1.1     什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存.

  4. Mybatis学习(五)————— 延迟加载和缓存机制(一级二级缓存)

    一.延迟加载 延迟加载就是懒加载,先去查询主表信息,如果用到从表的数据的话,再去查询从表的信息,也就是如果没用到从表的数据的话,就不查询从表的信息.所以这就是突出了懒这个特点.真是懒啊. Mybati ...

  5. Mybatis(五) 延迟加载和缓存机制(一级二级缓存)

    踏踏实实踏踏实实,开开心心,开心是一天不开心也是一天,路漫漫其修远兮. --WH 一.延迟加载 延迟加载就是懒加载,先去查询主表信息,如果用到从表的数据的话,再去查询从表的信息,也就是如果没用到从表的 ...

  6. mybatis学习--缓存(一级和二级缓存)

    声明:学习摘要! MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级) ...

  7. Mybatis五(一级二级缓存、第三方缓存)

    一级缓存 Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言.所以在参数和SQL完全一样的情况下,我们使用同一个SqlSess ...

  8. 深入理解MyBatis中的一级缓存与二级缓存

    http://blog.csdn.net/weixin_36380516/article/details/73194758   先说缓存,合理使用缓存是优化中最常见的,将从数据库中查询出来的数据放入缓 ...

  9. Mybatis延迟加载, 一级缓存、二级缓存

    延迟加载 概念:MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询.延迟加载可以有效的减少数据库压力. (注意:MyBatis的延迟加载只 ...

随机推荐

  1. Microsoft Visual Studio提示正忙如何解决

    打开项目的时候会一直提示正在加载,然后卡死,点击VS界面即出现下如图- 如图: 解决方法: 1.打开项目 找到一个叫vs的文件夹, 2.找到一个后缀是.suo的文件 把它删掉 3.关闭VS进程 重新打 ...

  2. Unity事件系统EventSystem简析

    相关组件和类 EventSystem 1.负责InputModule的切换(因为现在游戏大部分都只有一个StanaloneInputModule,所以切换这部分可以先不考虑). 2.负责InputMo ...

  3. Codeforces I Wanna Be the Guy 题解

    这道题非常简单,有两种做法: 1. 用一个数组标记是不是每个关卡小X或小Y都可以通过 2. 用set储存小X和小Y能够通过的关卡(set有去重功能),最后判断set的长度是否等于n 因为楼上已经有第一 ...

  4. CTF中关于XXE(XML外部实体注入)题目两道

    题目:UNCTF-Do you like xml? 链接:http://112.74.37.15:8008/ hint:weak password (弱密码) 1.观察后下载图片拖进WINHEX发现提 ...

  5. 使用静态URL片段 URL路由 精通ASP-NET-MVC-5-弗瑞曼

  6. 龙芯 Fedora 28 设置 VNC

    系统为龙芯版Fedora28 (床28) Fedora防火墙默认阻止了VNC所需的端口的访问,导致VNC客户端一直无法连接. 安装VNC Server sudo dnf install tigervn ...

  7. 事务管理(ACID)

    目录 一.事务管理(ACID) 原子性(Atomicity) 一致性(Consistency) 持久性(Durability) 隔离性(Isolation) 二.事务隔离级别 脏读 不可复读 虚读(幻 ...

  8. Leetcode 题目整理-3 Palindrome Number & Roman to Integer

    9. Palindrome Number Determine whether an integer is a palindrome. Do this without extra space. clic ...

  9. 曹工说Spring Boot源码(13)-- AspectJ的运行时织入(Load-Time-Weaving),基本内容是讲清楚了(附源码)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  10. 1751: n个素数构成等差数列

    #include <stdio.h>int fill(char *map,int *primes) { for (int i = 2; i < 1001; i++) { map[i] ...