带你深入理解MyBatis缓存机制

网友投稿 818 2022-12-02

带你深入理解MyBatis缓存机制

带你深入理解MyBatis缓存机制

目录一、简介1、缓存机制介绍2. 一级缓存和二级缓存二、一级缓存三、二级缓存3.1 mybatis自带的二级缓存3.1.1 代码测试二级缓存GInNMzE3.1.2 查询结果存入二级缓存的时机3.1.3 二级缓存相关配置四、整合EHCache4.1 EHCache简介4.2 整合操作五、缓存基本原理5.1 Cache接口5.2 PerpetualCache总结

一、简介

1、缓存机制介绍

当客户端发起一次查询请求时,首先通过java程序进行网络传输访问mysql数据库及对应的数据的服务器硬盘,当第二次的请求也是查询相同的数据时再通过这个流程显然有点“浪费”上次请求访问到的资源,所以我们将第一次查询到的数据存到缓存区域,当发生下一次相同请求时直接在缓存区域拿就行了。

2. 一级缓存和二级缓存

①使用顺序

查询的顺序是:

先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。

如果二级缓存没有命中,再查询一级缓存

如果一级缓存也没有命中,则查询数据库

SqlSession关闭之前,一级缓存中的数据会写入二级缓存

②效用范围

一级缓存:SqlSession级别二级缓存:SqlSessionFactory级别

它们之间范围的大小参考下面图:

二、一级缓存

当使用相同查询条件查询数据时,一共只打印了一条SQL语句,两个变量指向同一个对象。

一级缓存失效的情况:

不是同一个SqlSession

同一个SqlSession但是查询条件发生了变化

同一个SqlSession两次查询期间执行了任何一次增删改操作

同一个SqlSession两次查询期间手动清空了缓存

同一个SqlSession两次查询期间提交了事务

三、二级缓存

3.1 mybatis自带的二级缓存

3.1.1 代码测试二级缓存

① 开启二级缓存功能

在想要使用二级缓存的Mapper配置文件中加入cache标签

②让实体类支持序列化

public class Employee implements Serializable {

③junit测试

这个功能的测试操作需要将SqlSessionFactory对象设置为成员变量

public class CacheTest {

private SqlSessionFactory factory;

@Before

public void init() throws IOException {

factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));

}

//测试二级缓存,(mybatis自带的)

@Test

public void test1(){

SqlSession session = factory.openSession();

EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);

Employee employee = mapper.selectEmpById(2);

System.out.println("employee = " + employee);

//在执行第二次查询前,关闭当前SqlSession

session.close();

//开启新的SqlSession

session = factory.openSession();

mapper = session.getMapper(EmployeeMapper.class);

employee = mapper.selectEmpById(2);

System.out.println("employee = " + employee);

session.close();

}

}

打印效果:

22:48:18.669 [main] DEBUG com.zengchuiyu.mybatis.dao.EmployeeMapper - Cache Hit Ratio [com.zengchuiyu.mybatis.dao.EmployeeMapper]: 0.5

④缓存命中率

日志中打印的Cache Hit Ratio叫做缓存命中率

Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.0(0/1)

Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.5(1/2)

Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.6666666666666666(2/3)

Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.75(3/4)

Cache Hit Ratio [com.atguigu.mybatis.EmployeeMapper]: 0.8(4/5)

缓存命中率=命中缓存的次数/查询的总次数

3.1.2 查询结果存入二级缓存的时机

结论:SqlSession关闭的时候,一级缓存中的内容会被存入二级缓存

3.1.3 二级缓存相关配置

eviction属性:缓存回收策略

LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。

FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。

SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

默认的是 LRU。

flushInterval属性:刷新间隔,单位毫秒

默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

size属性:引用数目,正整数

代表缓存最多可以存储多少个对象,太大容易导致内存溢出

readOnly属性:只读,true/false

true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。

false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。

四、整合EHCache

4.1 EHCache简介

官网地址:https://ehcache.org/

Ehcache is an open source, standards-based cache that boosts performance, offloads your database, and simplifies scalability. It's the most widely-used Java-based cache because it's robust, proven, full-featured, and integrates with other popular libraries and frameworks. Ehcache scales from in-process caching, all the way to mixed in-process/out-of-process deployments with terabyte-sized caches.

Ehcache是一个开源的,基于标准的缓存,可以提高性能,卸载数据库,简化可伸缩性。它是最广泛使用的基于java的缓存,因为它健壮、可靠、功能齐全,并与其他流行的库和框架集成。Ehcache从进程内缓存扩展到具有tb大小缓存的进程内/进程外混合部署

4.2 整合操作

①Mybatis环境

在Mybatis环境下整合EHCache,前提当然是要先准备好Mybatis的环境。

②添加依赖

依赖信息:

org.mybatis.caches

mybatis-ehcache

1.2.1

ch.qos.logback

logback-classic

1.2.3

依赖传递情况:

各主要jar包作用

jar包名称

作用

mybatis-ehcache

Mybatis和EHCache的整合包

ehcache

EHCache核心包

slf4j-api

SLF4J日志门面包

logback-classic

支持SLF4J门面接口的一个具体实现

③整合EHCache

[1]创建EHCache配置文件

ehcache.xml

[2]文件内容

xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

maxElementsInMemory="1000"

maxElementsOnDisk="10000000"

eternal="false"

overflowToDisk="true"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU">

xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

maxElementsInMemory="1000"

maxElementsOnDisk="10000000"

eternal="false"

overflowToDisk="true"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU">

maxElementsInMemory="1000"

maxElementsOnDisk="10000000"

eternal="false"

overflowToDisk="true"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU">

引入第三方框架或工具时,配置文件的文件名可以自定义吗?

可以自定义:文件名是由我告诉其他环境

不能自定义:文件名是框架内置的、约定好的,就不能自定义,以避免框架无法加载这个文件

④加入logback日志

存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。

[1]各种Java日志框架简介

门面:

名称

说明

JCL(Jakarta Commons Logging)

陈旧

SLF4J(Simple Logging Facade for Java)★

适合

jboss-logging

特殊专业领域使用

实现:

名称

说明

log4j★

最初版

JUL(java.util.logging)

JDK自带

log4j2

Apache收购log4j后全面重构,内部实现和log4j完全不同

logback★

优雅、强大

[2]logback配置文件

class="ch.qos.logback.core.ConsoleAppender">

[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n

class="ch.qos.logback.core.ConsoleAppender">

[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n

⑤ EHCache配置文件说明

当借助CacheManager.add(“缓存名称”)创建Cache时,EhCache便会采用指定的的管理策略。http://

defaultCache标签各属性说明:

五、缓存基本原理

5.1 Cache接口

① 顶级接口

org.apache.ibatis.cache.Cache接口:所有缓存都必须实现的顶级接口

② Cache接口中的方法

③ 缓存的本质

根据Cache接口中方法的声明我们能够看到,缓存的本质是一个Map。

5.2 PerpetualCache

org.apache.ibatis.cache.impl.PerpetualCache是Mybatis的默认缓存,也是Cache接口的默认实现。Mybatis一级缓存和自带的二级缓存都是通过PerpetualCache来操作缓存数据的。但是这就奇怪了,同样是PerpetualCache这个类,怎么能区分出来两种不同级别的缓存呢?

其实很简单,调用者不同。

一级缓存:由BaseExecutor调用PerpetualCache

二级缓存:由CachingExecutor调用PerpetualCache,而CachingExecutor可以看做是对BaseExecutor的装饰

总结

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:OpenCV学习笔记-霍夫圆变换
下一篇:HTML5
相关文章

 发表评论

暂时没有评论,来抢沙发吧~