【Mybatis源码解析】一级缓存和二级缓存源码解析

news2024/9/20 22:47:17

文章目录

    • 缓存使用
    • 缓存源码
    • 测试代码

上一篇《【Mybatis源码解析】mapper实例化及执行流程源码分析》,主要讲解了Mybatis的基本原理一级执行的流程,这一章来讲一下Mybatis的两个缓存:一级缓存和二级缓存。

因为网上大部分都是使用xml配置的方式来使用缓存,所以我们这里讲解一下注解的方式。

一级缓存
一级缓存是SqlSession级别。一级缓存的作用域是 SqlSession , Mabits 默认开启一级缓存。 在同一个SqlSession中,执行相同的SQL查询时;第一次会去查询数据库,并写在缓存中,第二次会直接从缓存中取。 当执行SQL时候两次查询中间发生了增删改的操作,则SqlSession的缓存会被清空。

一级缓存 Mybatis的内部使用一个HashMap,key为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。 Sqlsession执行insert、update、delete等操作commit后会清空该SqlSession缓存。

  1. MyBatis一级缓存的生命周期和SqlSession一致。每次执行update前都会清空localCache。

  2. MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。

  3. MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement,即关闭一级缓存。

二级缓存
二级缓存是Mapper级别的缓存,多个SqlSession去操作同一个Mapper中的sql语句,则这些SqlSession可以共享二级缓存,即二级缓存是跨SqlSession的。简单说就是同一个namespace 下的 mapper 映射文件中,用相同的sql去查询数据,会去对应的二级缓存内取结果。

MyBatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。

MyBatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。

在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis、Memcached等分布式缓存可能成本更低,安全性也更高。

总结: 生产上建议关闭一级和二级缓存。

缓存使用

yml配置:

mybatis:
  configuration:
    # 驼峰大小写经典 Java 属性名 aColumn 的自动映射,默认值为false
    map-underscore-to-camel-case: true
    # statement: 关闭一级缓存;session:开启一级缓存 默认为session
    local-cache-scope: session
    # 开启二级缓存 默认为true
    cache-enabled: true
    # 打印sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

mapper接口(注解版):

@CacheNamespace注解:
作用于mapper接口上面,是用来实现二级缓存的,如果不指定实现类的话,默认就是PerpetualCache(实际上就是hashmap实现的)

@CacheNamespaceRef注解:
在多个命名空间中共享相同的缓存配置和实例

@Options(useCache = true,flushCache = Options.FlushCachePolicy.DEFAULT)注解:
useCache :是否用缓存,默认为true。
flushCache :是否刷新缓存,默认不刷新。

mapper接口(xml版):略。

在这里插入图片描述

缓存源码

新版的源码并没有太多改变,发送请求时,先从二级缓存中取,未取到则去一级缓存中取,仍未取到会去数据库中查,再存到一级缓存中,当事务提交之后,会存到二级缓存中,值得注意的是,mybatis中的一些cashe相关类挺有意思的,用来解决不同场景的问题,比如脏读。因为源码比较简单易懂,确实没什么值得可以写的,我想大家cv一下我的demo,debug一下应该就明白了。

在这里插入图片描述
在这里插入图片描述

  1. Mybatis在生产环境,是否应该开启缓存功能
  2. mybatis 开启二级缓存
  3. Mybatis开启本地二级缓存和使用redis开启二级缓存
  4. Mybatis 之 二级缓存
  5. 你尝试过在mybatis某个mapper上同时配置<cache/>和<cache-ref/>吗?
  6. Mybatis缓存源码分析

测试代码

controller

package com.ossa.web3.controller;

import com.ossa.web3.bean.User;
import com.ossa.web3.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class TestController {

    @Autowired
    private UserMapper userMapper;

    @GetMapping("/l1cache")
    @Transactional
    public User l1cache() {
        User user1 = userMapper.selectById("c5329f3b-3e98-4722-8faf-e87d9b981871");
        User user2 = userMapper.selectById("c5329f3b-3e98-4722-8faf-e87d9b981871");
        return null;
    }

    @GetMapping("/l2cache")
    public User l2cache() {
        return userMapper.selectById("c5329f3b-3e98-4722-8faf-e87d9b981871");
    }

    @DeleteMapping("/deleteById")
    public User deleteById() {
        return userMapper.deleteById("c5329f3b-3e98-4722-8faf-e87d9b981871");
    }
}

实体类

package com.ossa.web3.bean;

import lombok.Data;

import java.io.Serializable;

@Data
public class User implements Serializable {

    private String id;

    private String name;

    private Integer age;
}

mapper接口

package com.ossa.web3.mapper;

import com.ossa.web3.bean.User;
import org.apache.ibatis.annotations.*;

@CacheNamespace
public interface UserMapper {

    @Select(value = "select * from user where id = #{id}")
    @Options(useCache = true,flushCache = Options.FlushCachePolicy.DEFAULT)
    User selectById(String id);

    @Delete(value = "delete from user where id = #{id}")
    @Options(useCache = false,flushCache = Options.FlushCachePolicy.TRUE)
    User deleteById(String id);
}

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://issavior-aliyun-rds.mysql.rds.aliyuncs.com:3306/test?useUnicode=true&charsetEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
    username: root
    password: root

mybatis:
  configuration:
    # 驼峰大小写经典 Java 属性名 aColumn 的自动映射,默认值为false
    map-underscore-to-camel-case: true
    # statement: 关闭一级缓存;session:开启一级缓存
    local-cache-scope: session
    # 开启二级缓存
    cache-enabled: true
    # 打印sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl


############### Sa-Token 配置 (文档: https://sa-token.cc) ##############
#sa-token:
#  # token名称 (同时也是cookie名称)
#  token-name: satoken
#  # token有效期,单位s 默认30, -1代表永不过期
#  timeout: 2592000
#  # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
#  activity-timeout: -1
#  # 是否允许同一账号并发登录 (true时允许一起登录,false时新登录挤掉旧登录)
#  is-concurrent: true
#  # 在多人登录同一账号时,是否共用一个token (true时所有登录共用一个token,false时每次登录新建一个token)
#  is-share: true
#  # token风格
#  token-style: uuid
#  # 是否输出操作日志
#  is-log: false

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/352230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

函数编程之Function

文章目录前言一、Function是什么?二、Function 怎么用?1.简单使用2.真正的强大之处总结前言 在java8之后,我已经习惯了开始用stream()方式编程,但是对于新引入的其他功能,还是不清楚,今天经历了一个编程问题后,让我对于Function() 这个函数有了新的认知; 一、Func…

渲染农场优势是什么_云渲染农场怎么用?

在回答渲染农场的优势这个问题之前,我先申明一下本文中提到的渲染农场/云渲染平台/云渲染农场,都特指CG领域内的专业3D渲染平台,有一些文章会强调这个叫法的区别,但是业内一般都不会分这么细,所以也就不赘述了。渲染农…

【Spark分布式内存计算框架——Spark SQL】7. 数据处理分析案例

4.3 案例:电影评分数据分析 使用电影评分数据进行数据分析,分别使用DSL编程和SQL编程,熟悉数据处理函数及SQL使用,业务需求说明: 对电影评分数据进行统计分析,获取Top10电影(电影评分平均值最高…

4道数学题,求解极狐GitLab CI 流水线|第23题:父子流水线 + 多项目流水线

本文来自: 武让 极狐(GitLab) 高级解决方案架构师 💡 极狐GitLab CI 依靠其一体化、轻量化、声明式、开箱即用的特性,在开发者群体中的使用率越来越高,在国内企业中仅次于 Jenkins ,排在第二位。 极狐GitLab 流水线有…

如何解决错误“已超过了锁请求超时时段。 (Microsoft SQL Server,错误: 1222)“

解决 Microsoft SQL Server 的错误: 1222 使用存储过程 sp_who2设置 LOCK_TIMEOUT在Microsoft SQL Server Management Studio中,有时会在对象资源管理器中查看树、表或过程时收到错误。当查询等待的时间超过锁定超时设置时,通常会发生此错误。锁定超时以毫秒为单位,等待后端…

LeetCode 382. 链表随机节点

原题链接 难度:middle\color{orange}{middle}middle 题目描述 给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 被选中的概率一样 。 实现 SolutionSolutionSolution 类: Solution(ListNodehead)Solution…

数据库(第五次作业)

1.1 Redis概述 1.1.1 什么是Redis 2008年,意大利的一家创业公司Merzia推出了一款基于MySQL的网站实时统计系统LLOOGG,然而没过多久该公司的创始人 Salvatore Sanfilippo便开始对MySQL的性能感到失望,于是他决定亲自为LLOOGG量身定做一个数据…

Amazon S3简介

前言: 这段时间来到了某大数据平台,做平台技术底座封装和一些架构等等,有结构化数据也有非结构数据,涉及到很多技术,自己也私下花时间去研究了很多,有很多纯技术类的还是需要梳理并记录,巩固以及…

保姆级教程:Win10远程连接MACBook、MACBook远程连接Win10。

本篇给大家展示Windows远程连接连接MACBook、MACBook远程连接Windows的方法。需要明确的是,这种通过TCP远程连接的远程很稳定,基本比向日葵等软件流畅很多,但是缺点是需要保证在同一网域下,也就是同一局域网下,部分情况…

中国协同办公的终局是什么?

换言之,工具一体化是基本要求,但基于全链路集成的生态则是因地制宜、于当下的产业探索。 作者|斗斗 编辑|皮爷 出品|产业家 “计划裁员1300人,占到全球员工的15%。”美国东部时间2月7日,Zoom CEO袁征在官网博客发布公开信…

【SpringBoot】分布式日志跟踪—通过MDC实现全链路调用日志跟踪

一.MDC 1.MDC介绍 MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程场景下记录日志的功能。MDC 可以看成是一个与当前线程绑定的Map,可以往其中添加键值对。MDC 中包含的内容可以被同…

Python机器学习入门笔记(2)—— 分类算法

目录 转换器(transformer)和估计器(estimator) K-近邻(K-Nearest Neighbors,简称KNN)算法 模型选择与调优 交叉验证(Cross-validation) GridSearchCV API 朴素贝叶…

UE4 渲染学习笔记(未完)

原文链接:虚幻4渲染管线入门 - 知乎 从原文摘抄一下: 渲染框架 1,一套是传统的以RHICmdList为核心构建RenderPass,从RHICmdList.BeginRenderPass(...)开始,以RHICmdList.EndRenderPass()结束的框架。 2.一套是以新的Gr…

【面向对象语言三大特性之 “继承”】

目录 1.继承的概念及定义 1.1继承的概念 1.2 继承定义 1.2.1定义格式 1.2.2继承关系和访问限定符 1.2.3继承基类成员访问方式的变化 2.基类和派生类对象赋值转换 3.继承中的作用域 4.派生类的默认成员函数 5.继承与友元 6. 继承与静态成员 7.复杂的菱形继承及菱形虚拟…

linux(全志)初始环境到移植lvgl

一、 格式化TF卡 1. linux命令行格式化 1.1 找到U盘位置(已挂载) sudo fdisk -l 如图,我的在/dev/sdb 1.2 格式化U盘 sudo mkfs -t vfat /dev/sdb-t 后面是格式化为哪种文件系统格式,vfat就是fat32格式,最后…

Hashmap链表长度大于8真的会变成红黑树吗?

1、本人博客《HashMap、HashSet底层原理分析》 2、本人博客《若debug时显示的Hashmap没有table、size等元素时,查看第19条》 结论 1、链表长度大于8时(插入第9条时),会触发树化(treeifyBin)方法,但是不一定会树化,若数组大小小于…

Win11电脑速度慢、延迟高怎么办?

作为新版的系统,Windows 11还需要更多的时间完善。不少用户反映升级了Win11后反而感觉速度慢,还有延迟或死机现象。 如果你使用Win11系统时也有这种感觉,那这篇文章就是为你提供的。 问题可能出在系统存储容量低、驱动程序已过时&#xff0…

APP渗透抓包

APP渗透抓包1.APP渗透测试原理2.安装安卓模拟器抓包2.1.安装模拟器2.2.设置代理下载证书2.2.1.burp suite设置代理2.2.2.浏览器设置代理2.2.3.下载证书2.3.模拟器安装证书2.3.1.移动证书2.3.2.证书设置2.4.设置代理2.4.1.设置burp suite代理2.4.2.夜神模拟器代理2.5.抓包测试2.…

JVM调优及垃圾回收GC

一、说一说JVM的内存模型。JVM的运行时内存也叫做JVM堆,从GC的角度可以将JVM分为新生代、老年代和永久代。其中新生代默认占1/3堆内存空间,老年代默认占2/3堆内存空间,永久代占非常少的对内存空间。新生代又分为Eden区、SurvivorFrom区和Surv…

Node.js安装与配置

Node.js安装与配置 前言 本篇博文记录了Node.js安装与环境变量配置的详细步骤,旨在为将来再次配置Node.js时提供指导方法。 另外:Node.js版本请根据自身系统选择,安装位置、全局模块存放位置和环境变量应根据自身实际情况进行更改。 Node…