【Mybatis】 -- 架构分层 + 缓存机制

一、mybatis的架构分层与模块划分

mybatis整体架构分类:

【Mybatis】 -- 架构分层 + 缓存机制_第1张图片

接口层:

与用户应用打交道最多,核心对象是sqlSession;是上层应用和myBatis打交道的桥梁;
接口层定义了很多对数据库操作的方法,接口层在收到调用请求的时候,会调用核心处理层的响应模块来完成具体的数据库操作。

核心处理层:

跟数据库操作相关的动作都是在此完成

  • 把接口中传入的参数解析并映射成jdbc类型
  • 解析xml文件的sql语句,包括插入参数和动态sql生成
  • 执行sql语句
  • 处理结果集,并映射成java对象

基础支持层

  • 抽取一些通用的功能(实现复用),比如数据源,缓存,日志,xml解析,反射,IO,事务等

二、mybatis的缓存机制

所有缓存必须实现的接口Cache
默认的实现类PerpetualCache (基础的缓存实现类)
decorators包–缓存装饰类,装饰器模式
提供了增强缓存功能的各种实现类(日志,定时清理等带淘汰策略的)

2.1 一级缓存

作用域:session级别的, sqlsession内共享换从

如何开启一级缓存

一级缓存是默认开启的;
如何关闭一级缓存?

默认实现DefalutSqlSession,一级缓存是放在会话内部的执行器Executor的,
三种类型的执行器:simple,reuse,batch都有一个共同的父类–BaseExecutor
BaseExecutor通过PerpetualCache实现了一级缓存,也叫本地存储

总结:

用户查询时会先通过执行器获取会话内的一级缓存,如果命中就直接走缓存,没有缓存走库,然后写入缓存
增删改会默认清空缓存,原因是update/insert/delete标签的flashCash=ture 默认的;select标签的默认为false

【Mybatis】 -- 架构分层 + 缓存机制_第2张图片
一级缓存的脏数据:
由于一级缓存是会话内的,当其他会话对数据做了增删改操作的时候,本地会话并不知情,并不会清空缓存,所以查到的数据并不是最新的数据;

2.2 二级缓存

为了解决分布式会话或者多会话产生脏数据的情况,引入了作用范围更广的缓存–二级缓存
核心实现:使用装饰器模式用cachingExecutor包装Executor,作用范围更广

作用域:

namespace级别
在映射器级别 统一命名空间下 也就是同一个接口里面 相同方法的调用使用同一个缓存;

【Mybatis】 -- 架构分层 + 缓存机制_第3张图片

如何开启二级缓存:

在mybatis-config.xml全局配置文件中开启
其实,默认为true
在mapper.xml文件里面 添加才会生效
属性配置:
【Mybatis】 -- 架构分层 + 缓存机制_第4张图片
size: 缓存大小
eviction : 淘汰策略

  • LRU(Least Recently Use-- 最近最少使用的) – 默认使用
  • FIFO 先进先出
  • WEAK 基于jvm的弱引用
  • SOFT 基于jvm的软引用

flushInterval: 缓存多久被自动清空一次 (默认增删改时候清空 )
readOnly :是否只读 ( 默认false)

  • false 可以读写,返回的是对象的copy, 所以要实现序列化接口,更安全
  • true 只读,返回的是同一个对象,更快

二级缓存与一级缓存先后顺序?

开启了二级缓存之后,会先走二级缓存再走一级缓存(二级缓存更广,先走外面的)

思考:

被多个sqlsession共享的话我们应该将缓存放在什么位置呢?
在装饰包里Executor有一个高级实现类–casheExecutor`
casheExecutor会对baseExecutor做一个装饰,casheExecutor是外部的装饰者,baseExecutor是内部的被装饰着
casheExecutor内有一个Executor是基于TransactionalCacheManager来实现的,带事务性的缓存,所以二级支持添加多个或删除多个缓存;

不推荐使用二级缓存的原因

示例说明:
在一个namespace里面,只要有任意一个会话执行了增删改的操作,都会清空同一个namespace下的缓存;
带来的问题,若增删改操作很多,缓存会被频繁的清空,二级缓存将会失去意义,
所以建议用于查询为主的业务
一般情况下一个namespace操作一张表,若其他namespace的也操作了这张表同样会造成脏读;

【Mybatis】 -- 架构分层 + 缓存机制_第5张图片

引入第三方组件做二级缓存:
image.png
实际情况下:
我们通常会引入第三方独立的缓存,例如redis,提供了更多持久化的策略

你可能感兴趣的:(mybatis)