Mybatis 一级缓存,Mybatis 二级缓存,Mybatis 缓存失效

================================

©Copyright 蕃薯耀 2021-06-24

https://blog.csdn.net/w995223851

一、SpringBoot整合Mybatis

1、pom.xml引入依赖(基于SpringBoot:2.3.12.RELEASE)


<properties><!-- JDK版本 --><java.version>1.8</java.version><!-- 构建时编码 -->  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- 输出时编码 --><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 5.1.49 --><!-- 8.0.25 --><mysql.version>5.1.49</mysql.version>
</properties><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- 2.2.0 -->
<!-- 2.1.4 -->
<!--
master(2.2.x) : MyBatis 3.5+, MyBatis-Spring 2.0+(2.0.6+ recommended), Java 8+ and Spring Boot 2.5+
2.1.x : MyBatis 3.5+, MyBatis-Spring 2.0+(2.0.6+ recommended), Java 8+ and Spring Boot 2.1-2.4mybatis-spring-boot-starter自动配置:
Autodetect an existing DataSource
Will create and register an instance of a SqlSessionFactory passing that DataSource as an input using the SqlSessionFactoryBean
Will create and register an instance of a SqlSessionTemplate got out of the SqlSessionFactory
Auto-scan your mappers, link them to the SqlSessionTemplate and register them to Spring context so they can be injected into your beans翻译:
自动检测现有数据源
将创建和注册 SqlSessionFactory 的实例,使用 SqlSessionFactoryBean 将该数据源作为输入传递
将创建并注册一个从 SqlSessionFactory 中得到的 SqlSessionTemplate 的实例
自动扫描您的映射器,将它们链接到 SqlSessionTemplate 并将它们注册到 Spring 上下文,以便它们可以注入到您的 bean 中-->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>

2、application.properties配置文件修改


#数据库连接配置
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3307/db?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&pinGlobalTxToPhysicalConnection=true&autoReconnect=true
spring.datasource.driver-class-name=com.mysql.jdbc.Driver#Mybatis配置
#详细配置项见:
#https://mybatis.org/mybatis-3/configuration.html#settings
#扫描实体包作为别名
mybatis.type-aliases-package=com.lqy.entity
#驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true
#启动全局缓存,默认是true
mybatis.configuration.cache-enabled=true
#启动懒加载
mybatis.configuration.lazy-loading-enabled=true
#打印日志
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

3、启动类加上@MapperScan注解,自动扫描Mybatis Mapper包


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.lqy.mapper")
public class MybatisCacheApplication {public static void main(String[] args) {SpringApplication.run(MybatisCacheApplication.class, args);}}

Mybatis使用@MapperScan注解后,Mapper文件不需要再加@Mapper注解

4、创建Mapper接口

import org.apache.ibatis.annotations.Select;import com.lqy.entity.Student;public interface StudentMapper {@Select("select * from student where id = #{id}")public Student get(Long id);}

5、测试SpringBoot整合Mybatis


//slf4j
private Logger log =  LoggerFactory.getLogger(MybatisCacheController.class);@Resource
private StudentMapper studentMapper;@RequestMapping("/db/{id}")
public Result db(@PathVariable("id") Long id) {Student student = studentMapper.get(id);log.info("student is {}", student);return Result.ok(student);
}

二、Mybatis 一级缓存

1、Mybatis同一个会话(sqlSession),一级缓存生效

/*** Mybatis同一个会话(sqlSession),测试一级缓存*  结论:* Mybatis同一个会话,两次查询同一条数据,只打印了一条sql查询语句,一级缓存生效* @param id* @return*/
@RequestMapping("/sameSession/{id}")
public Result sameSession(@PathVariable("id") Long id) {SqlSession sqlSession = sqlSessionFactory.openSession();StudentMapper stuMapper1  =sqlSession.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession.getMapper(StudentMapper.class);Student student1 = stuMapper1.get(id);log.info("stuMapper1 student is {}", student1);Student student2 = stuMapper2.get(id);log.info("stuMapper2 student is {}", student2);sqlSession.close();return Result.ok(student1);
}

2021-06-23 11:13:03.125  INFO 9084 --- [io-4000-exec-10] o.a.c.c.C.[.[localhost].[/mybatisCache]  : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-06-23 11:13:03.126  INFO 9084 --- [io-4000-exec-10] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-06-23 11:13:03.135  INFO 9084 --- [io-4000-exec-10] o.s.web.servlet.DispatcherServlet        : Completed initialization in 9 ms
2021-06-23 11:13:03.137  INFO 9084 --- [io-4000-exec-10] com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Starting...
2021-06-23 11:13:03.143  INFO 9084 --- [io-4000-exec-10] com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Start completed.
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, null
<==      Total: 1
2021-06-23 11:13:03.146  INFO 9084 --- [io-4000-exec-10] c.lqy.controller.MybatisCacheController  : stuMapper1 student is com.lqy.entity.Student@2a61ea98
2021-06-23 11:13:03.146  INFO 9084 --- [io-4000-exec-10] c.lqy.controller.MybatisCacheController  : stuMapper2 student is com.lqy.entity.Student@2a61ea98

2、Mybatis不是同一个会话(sqlSession),一级缓存不生效

/*** Mybatis不是同一个会话(sqlSession),测试一级缓存* 结论:* Mybatis不是同一个会话,两次查询同一条数据,打印了两条sql查询语句,一级缓存不生效* @param id* @return*/
@RequestMapping("/notSameSession/{id}")
public Result notSameSession(@PathVariable("id") Long id) {SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();StudentMapper stuMapper1  =sqlSession1.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession2.getMapper(StudentMapper.class);Student student = stuMapper1.get(id);log.info("stuMapper1 student is {}", student);sqlSession1.close();Student student2 = stuMapper2.get(id);log.info("stuMapper2 student is {}", student2);sqlSession2.close();return Result.ok(student);
}

2021-06-23 11:30:31.334  INFO 188 --- [nio-4000-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Starting...
2021-06-23 11:30:31.339  INFO 188 --- [nio-4000-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Start completed.
JDBC Connection [HikariProxyConnection@1835684313 wrapping com.mysql.jdbc.JDBC4Connection@4d739d17] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, null
<==      Total: 1
2021-06-23 11:30:31.348  INFO 188 --- [nio-4000-exec-1] c.lqy.controller.MybatisCacheController  : =====stuMapper1 student is com.lqy.entity.Student@e4441a0
JDBC Connection [HikariProxyConnection@1594814042 wrapping com.mysql.jdbc.JDBC4Connection@4d739d17] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, null
<==      Total: 1
2021-06-23 11:30:31.353  INFO 188 --- [nio-4000-exec-1] c.lqy.controller.MybatisCacheController  : =====stuMapper2 student is com.lqy.entity.Student@4f28bd07

3、Mybatis同一个会话(sqlSession),两次查询之间做了更新操作(新增、删除、修改),一级缓存不生效(发送了2次查询sql)

/*** Mybatis同一个会话(sqlSession),两次查询之间做了更新操作(新增、删除、修改),一级缓存不生效* @param id* @return*/
@RequestMapping("/sameSessionUpdate/{id}")
public Result sameSessionUpdate(@PathVariable("id") Long id) {SqlSession sqlSession = sqlSessionFactory.openSession();StudentMapper stuMapper1  =sqlSession.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession.getMapper(StudentMapper.class);StudentMapper stuMapper3  =sqlSession.getMapper(StudentMapper.class);Student student1 = stuMapper1.get(id);log.info(logPrefix + "stuMapper1 student is {}", student1);//两次查询之间做了更新操作(新增、删除、修改)stuMapper3.update(id);Student student2 = stuMapper2.get(id);log.info(logPrefix + "stuMapper2 student is {}", student2);sqlSession.close();return Result.ok(student1);
}

JDBC Connection [HikariProxyConnection@1830365917 wrapping com.mysql.jdbc.JDBC4Connection@1fa708f1] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 14:34:15.775  INFO 3228 --- [nio-4000-exec-2] c.lqy.controller.MybatisCacheController  : =====stuMapper1 student is com.lqy.entity.Student@67e141ad
==>  Preparing: update student set remark = ? where id = ?
==> Parameters: 1(Long), 1(Long)
<==    Updates: 1
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 14:34:15.818  INFO 3228 --- [nio-4000-exec-2] c.lqy.controller.MybatisCacheController  : =====stuMapper2 student is com.lqy.entity.Student@42cc3c7a

4、 Mybatis同一个会话(sqlSession),手动清除缓存后的一级缓存不生效。因为手动清除缓存已经没有缓存:sqlSession.clearCache()

/*** Mybatis同一个会话(sqlSession),手动清除缓存后的一级缓存不生效。因为手动清除缓存已经没有缓存:sqlSession.clearCache()*  结论:* @param id* @return*/
@RequestMapping("/sameSessionClearCache/{id}")
public Result sameSessionClearCache(@PathVariable("id") Long id) {SqlSession sqlSession = sqlSessionFactory.openSession();StudentMapper stuMapper1  =sqlSession.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession.getMapper(StudentMapper.class);Student student1 = stuMapper1.get(id);log.info(logPrefix + "stuMapper1 student is {}", student1);sqlSession.clearCache();Student student2 = stuMapper2.get(id);log.info(logPrefix + "stuMapper2 student is {}", student2);sqlSession.close();return Result.ok(student1);
}

2021-06-23 14:38:52.228  INFO 3228 --- [nio-4000-exec-4] com.zaxxer.hikari.HikariDataSource       : HikariPool-4 - Starting...
2021-06-23 14:38:52.235  INFO 3228 --- [nio-4000-exec-4] com.zaxxer.hikari.HikariDataSource       : HikariPool-4 - Start completed.
JDBC Connection [HikariProxyConnection@1539770887 wrapping com.mysql.jdbc.JDBC4Connection@3975b4fb] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 14:38:52.240  INFO 3228 --- [nio-4000-exec-4] c.lqy.controller.MybatisCacheController  : =====stuMapper1 student is com.lqy.entity.Student@528bc92f
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 14:38:52.242  INFO 3228 --- [nio-4000-exec-4] c.lqy.controller.MybatisCacheController  : =====stuMapper2 student is com.lqy.entity.Student@7dea6ddf

5、总结:
Mybatis 一级缓存(会话级别缓存:sqlSession)默认是开启的。

Mybatis 一级缓存失效的情况:
(1)、非同一个sqlSession(两个不同的sqlSession)
(2)、同一个sqlSession,查询条件不同(查询条件不同,相应的数据还没有放到缓存)
(3)、同一个sqlSession,两次查询之间做了更新操作(新增、删除、修改)
(4)、同一个sqlSession,两次查询之间做了缓存清除:sqlSession.clearCache()

三、Mybatis 二级缓存

Mybatis 二级缓存启用:
(1)、需要开启全局二级缓存:在application.properties文件配置:mybatis.configuration.cache-enabled=true,cache-enabled默认是开启的,即可以配置也可以不配置

(2)、需要在XxxMapper的接口类上加上注解:@CacheNamespace,表示该Mapper开启二级缓存
示例:

@CacheNamespace
public interface StudentMapper {}

(3)、实体bean要实现Serializable接口

1、Mybatis同一个会话(sqlSession),两次查询同一条数据,只打印了一条sql查询语句,二级缓存生效
和一级缓存的区别是:开启二级缓存后 ,会有缓存命中率的打印(Cache Hit Ratio)

/*** Mybatis同一个会话(sqlSession),分别请求两次:* 第一次请求,两次查询同一条数据,只打印了一条sql查询语句,一级缓存生效* 第二次请求,两次查询同一条数据,没有打印sql查询语句,二级缓存生效* @param id* @return*/
@RequestMapping("/sameSession/{id}")
public Result sameSession(@PathVariable("id") Long id) {SqlSession sqlSession = sqlSessionFactory.openSession();StudentMapper stuMapper1  =sqlSession.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession.getMapper(StudentMapper.class);Student student1 = stuMapper1.get(id);log.info(logPrefix + "stuMapper1 student is {}", student1);Student student2 = stuMapper2.get(id);log.info(logPrefix + "stuMapper2 student is {}", student2);sqlSession.close();return Result.ok(student1);
}

第一次查询(一级缓存生效,发送了一次sql查询,二级缓存未命中(还没有二级缓存数据,只有在sqlSession关闭后才放到二级缓存)):
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.0
2021-06-23 15:15:15.752  INFO 10808 --- [nio-4000-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2021-06-23 15:15:16.032  INFO 10808 --- [nio-4000-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@1253127447 wrapping com.mysql.jdbc.JDBC4Connection@3072075a] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 15:15:16.072  INFO 10808 --- [nio-4000-exec-1] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@235995b6
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.0
2021-06-23 15:15:16.072  INFO 10808 --- [nio-4000-exec-1] c.lqy.controller.SecondCacheController   : =====stuMapper2 student is com.lqy.entity.Student@235995b6第二次查询(二级缓存已经命中,没有发送sql查询):
As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.3333333333333333
2021-06-23 15:20:11.201  INFO 10808 --- [nio-4000-exec-4] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@3890ca0c
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.5
2021-06-23 15:20:11.201  INFO 10808 --- [nio-4000-exec-4] c.lqy.controller.SecondCacheController   : =====stuMapper2 student is com.lqy.entity.Student@61e9e758

2、Mybatis不是一个会话(sqlSession),两次查询同一条数据,只打印了一条sql查询语句,第二次查询从二缓存命中,二级缓存生效

/*** Mybatis不是同一个会话(sqlSession)* 第一次请求,两次查询同一条数据,第一次查询打印了一条sql查询语句(一、二级缓存未生效),第二次查询(在第一次查询sqlSession关闭后,数据放到二级缓存),二缓存命中(一级缓存不生效),二级缓存生效* 第二次请求,两次查询同一条数据,没有打印sql查询语句,二级缓存生效* @param id* @return*/
@RequestMapping("/notSameSession/{id}")
public Result notSameSession(@PathVariable("id") Long id) {SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();StudentMapper stuMapper1  =sqlSession1.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession2.getMapper(StudentMapper.class);Student student = stuMapper1.get(id);log.info(logPrefix + "stuMapper1 student is {}", student);sqlSession1.close();Student student2 = stuMapper2.get(id);log.info(logPrefix + "stuMapper2 student is {}", student2);sqlSession2.close();return Result.ok(student);
}

第一次请求:
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.0
2021-06-23 15:33:33.868  INFO 1120 --- [nio-4000-exec-5] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2021-06-23 15:33:34.188  INFO 1120 --- [nio-4000-exec-5] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@1023753071 wrapping com.mysql.jdbc.JDBC4Connection@2ca9d629] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 15:33:34.229  INFO 1120 --- [nio-4000-exec-5] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@48b64b58
As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.5
2021-06-23 15:33:34.238  INFO 1120 --- [nio-4000-exec-5] c.lqy.controller.SecondCacheController   : =====stuMapper2 student is com.lqy.entity.Student@a654eb8第二次请求:
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.6666666666666666
2021-06-23 15:36:19.272  INFO 1120 --- [nio-4000-exec-9] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@13a150d5
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.75
2021-06-23 15:36:19.273  INFO 1120 --- [nio-4000-exec-9] c.lqy.controller.SecondCacheController   : =====stuMapper2 student is com.lqy.entity.Student@1d66bcd1

3、Mybatis同一个会话(sqlSession),两次查询之间做了更新操作(新增、删除、修改),一、二级缓存都不生效(发送了2次查询sql)

/*** Mybatis同一个会话(sqlSession),两次查询之间做了更新操作(新增、删除、修改),一、二级缓存都不生效(发送了2次查询sql)* @param id* @return*/
@RequestMapping("/sameSessionUpdate/{id}")
public Result sameSessionUpdate(@PathVariable("id") Long id) {SqlSession sqlSession = sqlSessionFactory.openSession();StudentMapper stuMapper1  =sqlSession.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession.getMapper(StudentMapper.class);StudentMapper stuMapper3  =sqlSession.getMapper(StudentMapper.class);Student student1 = stuMapper1.get(id);log.info(logPrefix + "stuMapper1 student is {}", student1);//两次查询之间做了更新操作(新增、删除、修改)stuMapper3.update(id);Student student2 = stuMapper2.get(id);log.info(logPrefix + "stuMapper2 student is {}", student2);sqlSession.close();return Result.ok(student1);
}

Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.0
2021-06-23 15:39:44.807  INFO 1120 --- [nio-4000-exec-6] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Starting...
2021-06-23 15:39:44.813  INFO 1120 --- [nio-4000-exec-6] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Start completed.
JDBC Connection [HikariProxyConnection@253872058 wrapping com.mysql.jdbc.JDBC4Connection@698c372c] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 15:39:44.817  INFO 1120 --- [nio-4000-exec-6] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@3a08debb
==>  Preparing: update student set remark = ? where id = ?
==> Parameters: 1(Long), 1(Long)
<==    Updates: 1
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.0
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 15:39:44.863  INFO 1120 --- [nio-4000-exec-6] c.lqy.controller.SecondCacheController   : =====stuMapper2 student is com.lqy.entity.Student@2231baba

4、Mybatis不是同一个会话(sqlSession),两次查询之间做了更新操作(新增、删除、修改),二级缓存生效
第一次请求:第一次查询发送了sql,一、二级缓存不生效。第二次查询,没有发送sql,二级缓存生效。
第二次请求:两次查询都没有发送sql,二级缓存生效

/*** Mybatis不是同一个会话(sqlSession),两次查询之间做了更新操作(新增、删除、修改),二级缓存生效* 第一次请求:第一次查询发送了sql,一、二级缓存不生效。第二次查询,没有发送sql,二级缓存生效* 第二次请求:两次查询都没有发送sql,二级缓存生效* @param id* @return*/
@RequestMapping("/notSameSessionUpdate/{id}")
public Result notSameSessionUpdate(@PathVariable("id") Long id) {SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();SqlSession sqlSession3 = sqlSessionFactory.openSession();StudentMapper stuMapper1  =sqlSession1.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession2.getMapper(StudentMapper.class);StudentMapper stuMapper3  =sqlSession3.getMapper(StudentMapper.class);Student student1 = stuMapper1.get(id);log.info(logPrefix + "stuMapper1 student is {}", student1);sqlSession1.close();//两次查询之间做了更新操作(新增、删除、修改)stuMapper3.update(id);sqlSession3.close();Student student2 = stuMapper2.get(id);log.info(logPrefix + "stuMapper2 student is {}", student2);sqlSession2.close();return Result.ok(student1);
}

第一次请求:第一次查询发送了sql,一、二级缓存不生效。第二次查询,没有发送sql,二级缓存生效Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.0
2021-06-23 15:45:16.757  INFO 1120 --- [nio-4000-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-4 - Starting...
2021-06-23 15:45:16.764  INFO 1120 --- [nio-4000-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-4 - Start completed.
JDBC Connection [HikariProxyConnection@1475826374 wrapping com.mysql.jdbc.JDBC4Connection@2204d9a4] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 15:45:16.767  INFO 1120 --- [nio-4000-exec-1] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@6a3d9b01
JDBC Connection [HikariProxyConnection@1775176572 wrapping com.mysql.jdbc.JDBC4Connection@2204d9a4] will not be managed by Spring
==>  Preparing: update student set remark = ? where id = ?
==> Parameters: 1(Long), 1(Long)
<==    Updates: 1
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.5
2021-06-23 15:45:16.811  INFO 1120 --- [nio-4000-exec-1] c.lqy.controller.SecondCacheController   : =====stuMapper2 student is com.lqy.entity.Student@207487b第二次请求:两次查询都没有发送sql,二级缓存生效Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.6666666666666666
2021-06-23 15:45:50.022  INFO 1120 --- [nio-4000-exec-2] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@311e46ff
JDBC Connection [HikariProxyConnection@1071230636 wrapping com.mysql.jdbc.JDBC4Connection@2204d9a4] will not be managed by Spring
==>  Preparing: update student set remark = ? where id = ?
==> Parameters: 1(Long), 1(Long)
<==    Updates: 1
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.75
2021-06-23 15:45:50.079  INFO 1120 --- [nio-4000-exec-2] c.lqy.controller.SecondCacheController   : =====stuMapper2 student is com.lqy.entity.Student@3d8e3c0a

5、Mybatis不是同一个会话(sqlSession),

第一次请求:一级缓存不生效(手动清除一级缓存:sqlSession.clearCache),二级缓存生效;

第二次请求:全部命中二级缓存,不发送sql,二级缓存生效

/*** Mybatis不是同一个会话(sqlSession)* 第一次请求:一级缓存不生效(手动清除一级缓存:sqlSession.clearCache),二级缓存生效* 第二次请求:全部命中二级缓存,不发送sql,二级缓存生效* @param id* @return*/
@RequestMapping("/sameSessionClearCache/{id}")
public Result sameSessionClearCache(@PathVariable("id") Long id) {SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession3 = sqlSessionFactory.openSession();//都是sqlSession1StudentMapper stuMapper1  =sqlSession1.getMapper(StudentMapper.class);StudentMapper stuMapper2  =sqlSession1.getMapper(StudentMapper.class);//sqlSession3StudentMapper stuMapper3  =sqlSession3.getMapper(StudentMapper.class);Student student1 = stuMapper1.get(id);log.info(logPrefix + "stuMapper1 student is {}", student1);//手动清除缓存sqlSession1.clearCache();//只清除一级缓存System.out.println(logSeparateLine);Student student2 = stuMapper2.get(id);log.info(logPrefix + "student2 student is {}", student2);sqlSession1.close();System.out.println(logSeparateLine);Student student3 = stuMapper3.get(id);log.info(logPrefix + "student3 student is {}", student3);sqlSession3.close();return Result.ok(student1);
}

第一次请求:
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.0
2021-06-23 16:03:26.164  INFO 1120 --- [nio-4000-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-8 - Starting...
2021-06-23 16:03:26.170  INFO 1120 --- [nio-4000-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-8 - Start completed.
JDBC Connection [HikariProxyConnection@276419536 wrapping com.mysql.jdbc.JDBC4Connection@20c9ed7d] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 16:03:26.172  INFO 1120 --- [nio-4000-exec-1] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@1d636554
--------------------------------------------------------------------------------------------------------------------
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.0
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 16:03:26.175  INFO 1120 --- [nio-4000-exec-1] c.lqy.controller.SecondCacheController   : =====student2 student is com.lqy.entity.Student@3e8c7bc6
--------------------------------------------------------------------------------------------------------------------
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.3333333333333333
2021-06-23 16:03:26.177  INFO 1120 --- [nio-4000-exec-1] c.lqy.controller.SecondCacheController   : =====student3 student is com.lqy.entity.Student@4c304786第二次请求:
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.5
2021-06-23 16:04:21.256  INFO 1120 --- [nio-4000-exec-2] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@8dc27a9
--------------------------------------------------------------------------------------------------------------------
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.6
2021-06-23 16:04:21.256  INFO 1120 --- [nio-4000-exec-2] c.lqy.controller.SecondCacheController   : =====student2 student is com.lqy.entity.Student@61bc8c2
--------------------------------------------------------------------------------------------------------------------
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.6666666666666666
2021-06-23 16:04:21.257  INFO 1120 --- [nio-4000-exec-2] c.lqy.controller.SecondCacheController   : =====student3 student is com.lqy.entity.Student@2244cd9

6、查询使用flushCache、useCache清除缓存:@Options(flushCache = FlushCachePolicy.TRUE, useCache = false),二级缓存不生效

/*** flushCache:是否清除缓存,默认是DEFAULT*   FlushCachePolicy.DEFAULT:如果是查询(select)操作,则是false,其它更新(insert、update、delete)操作则是true*   * useCache:是否将查询数据放到二级缓存* @param id*/
@Select("select * from student where id = #{id}")
@Options(flushCache = FlushCachePolicy.TRUE, useCache = false)
public Student get(Long id);

方法同二级缓存的:notSameSessionUpdate,现在缓存不生效JDBC Connection [HikariProxyConnection@806642975 wrapping com.mysql.jdbc.JDBC4Connection@7c12637c] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 16:28:29.394  INFO 1120 --- [nio-4000-exec-4] c.lqy.controller.SecondCacheController   : =====stuMapper1 student is com.lqy.entity.Student@3aec0e6f
JDBC Connection [HikariProxyConnection@2146338646 wrapping com.mysql.jdbc.JDBC4Connection@7c12637c] will not be managed by Spring
==>  Preparing: update student set remark = ? where id = ?
==> Parameters: 1(Long), 1(Long)
<==    Updates: 1
JDBC Connection [HikariProxyConnection@337545723 wrapping com.mysql.jdbc.JDBC4Connection@7c12637c] will not be managed by Spring
==>  Preparing: select * from student where id = ?
==> Parameters: 1(Long)
<==    Columns: id, stu_no, stu_name, age, clazz_id, create_time, remark
<==        Row: 1, 1, 学生一, null, null, 2021-04-26 19:01:29.0, 1
<==      Total: 1
2021-06-23 16:28:29.439  INFO 1120 --- [nio-4000-exec-4] c.lqy.controller.SecondCacheController   : =====stuMapper2 student is com.lqy.entity.Student@7a2c82a9

7、二级缓存结论:
当执行一条查询sql时,先从二级缓存进行查询,没有则进入一级缓存查询,再没有就执行sql进行数据库查询,在会话(sqlSession)结束前把缓存放到一级缓存,会话结束后放到二级缓存中(需要开启二级缓存)。

手动清除查询的二级缓存

@Options(flushCache = FlushCachePolicy.TRUE, useCache = false)
flushCache:是否清除缓存,默认是DEFAULT,可以直接设置FlushCachePolicy.TRUEFlushCachePolicy.DEFAULT:如果是查询(select)操作,则是false,其它更新(insert、update、delete)操作则是true
useCache:是否将查询结果放到二级缓存

四、Mybatis整合EhCache

1、pom.xml文件引入mybatis-ehcache依赖

<!-- 使用:http://mybatis.org/ehcache-cache/ -->
<dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.2.1</version>
</dependency>

2、Mapper类的缓存实现类改成:EhcacheCache.class

@CacheNamespace(implementation = EhcacheCache.class)
public interface StudentMapper {
}

3、增加ehcache.xml配置文件,放在classpath路径下(src/main/resources/ehcache.xml)

ehcache.xml内容如下:


<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="ehcache.xsd"updateCheck="true" monitoring="autodetect"dynamicConfig="true"><!-- ehcache 文件存放路径 --><diskStore path="C:\mybatis-cache"/><!--defaultCache:默认的管理策略--><!--eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断--><!--maxElementsInMemory:在内存中缓存的element的最大数目--><!--overflowToDisk:如果内存中数据超过内存限制,是否要缓存到磁盘上--><!--diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false--><!--timeToIdleSeconds:对象空闲时间(单位:秒),指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问--><!--timeToLiveSeconds:对象存活时间(单位:秒),指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问--><!--memoryStoreEvictionPolicy:缓存的3 种清空策略--><!--FIFO:first in first out (先进先出)--><!--LFU:Less Frequently Used (最少使用).意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存--><!--LRU:Least Recently Used(最近最少使用). (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存--><defaultCachemaxEntriesLocalHeap="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk=truediskPersistent=truediskSpoolBufferSizeMB="30"maxEntriesLocalDisk="10000000"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"><persistence strategy="localTempSwap"/></defaultCache></ehcache>

4、启动项目测试
路径C:\mybatis-cache下会多出ehcache的文件,二级缓存同时生效。

Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.5
Cache Hit Ratio [com.lqy.mapper.StudentMapper]: 0.6666666666666666

(时间宝贵,分享不易,捐赠回馈,^_^)

================================

©Copyright 蕃薯耀 2021-06-24

https://blog.csdn.net/w995223851

Mybatis 一级缓存,Mybatis 二级缓存,Mybatis 缓存失效相关推荐

  1. Mybatis一级缓存,二级缓存的实现就是这么简单

    介绍 又到了一年面试季,所以打算写一点面试常问的东西,争取说的通俗易懂.面试高级岗,如果你说熟悉Mybatis,下面这些问题基本上都会问 Mybatis插件的实现原理? 如何写一个分页插件? Myba ...

  2. (转)mybatis一级缓存二级缓存

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

  3. mybatis高级(3)_延迟加载_深度延迟_一级缓存_二级缓存

    设置延迟加载需要在mybatis.xml中设置 注: 侵入式延迟加载为真时是延迟加载 侵入式延迟加载为假时是深度延迟加载 <!-- 延迟加载和深度延迟加载 --><settings& ...

  4. Mybatis3.4.x技术内幕(二十二):Mybatis一级、二级缓存原理分析

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis的一级缓存,指的是SqlSession级别的缓存,默认开启:Mybatis的二级缓存,指的是SqlSession ...

  5. Mybatis一级缓存、二级缓存

    一级缓存:SqlSession mybatis一级缓存是指在内存中开辟一块区域,用来保存用户对数据库的操作信息(sql)和数据库返回的数据,如果下一次用户再执行相同的请求,那么直接从内存中读数数据而不 ...

  6. MyBatis框架:延迟加载策策略、一级缓存、二级缓存

    MyBatis框架:延迟加载策略和缓存 Mybatis 延迟加载策略 1.1 何为延迟加载? 1.2 实现需求 1.3 使用association实现延迟加载 1.3.1 账户的持久层DAO接口 1. ...

  7. swf缓存文件在哪里_面试官:mybatis一级缓存二级缓存的区别都不知道,知道门在哪吧...

    面试官:虫虫你简历上写了了解mybatis缓存,那你能说说一级缓存和二级缓存的区别吗? 虫虫:我只知道这是用来缓存sql查询的数据 面试官:没了? 虫虫:没了 面试官:公司门知道在哪里吧 自己走还是我 ...

  8. 浅谈Mybatis的一级缓存和二级缓存

    MyBatis的缓存机制 缓存的引入 当我们大量执行重复的查询SQL语句的时候,会频繁的和数据库进行通信,会增加查询时间等影响用户体验的问题,可以通过缓存,以降低网络流量,使网站加载速度更快. MyB ...

  9. mybatis一级缓存二级缓存

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

  10. MyBatis】MyBatis一级缓存和二级缓存

    转载自  MyBatis]MyBatis一级缓存和二级缓存 MyBatis自带的缓存有一级缓存和二级缓存 一级缓存 Mybatis的一级缓存是指Session缓存.一级缓存的作用域默认是一个SqlSe ...

最新文章

  1. 学术墙报模板_【学院动态】水产学院2020年研究生学术年会科研墙报评比活动开始...
  2. vue项目搜索历史功能的实现
  3. 普211标准三维EE零基础转CS申
  4. linux 英伟达 分辨率,配置nVidia显卡修改Ubuntu分辨率
  5. submodule切换分支_git子模块分支会随主项目的分支切换吗?
  6. 图片的base64编码实现以及网页上显示
  7. 单向队列、双端队列、栈的模型实现
  8. ansys怎么使用anand模型_当SpaceClaim 遇上ANSYS
  9. [转载] [转载] python中的Numpy库入门
  10. 网站跨域访问解决方法
  11. vscode还用装git_使用vscode实现git同步
  12. 推荐几个优秀的微信小程序UI组件库
  13. linux u盘 修复工具,在Linux终端中修复U盘驱动器问题
  14. 第一章:Python数据分析前的基础铺垫
  15. java:comp/env 解释
  16. 暄桐林曦老师浅谈“如何加强专注自律”
  17. MySQLdb._exceptions.OperationalError: (1045, “Access denied for user ‘root‘@‘localhost‘ (using passw
  18. Linux 命令————打包解压之tar
  19. 2021SC@SDUSC 开源项目GFPGAN -7-experiments
  20. Windows 10最新原版镜像(Version 21H1)

热门文章

  1. 浮点数的存储(Normalized Denormalized 特殊值)
  2. CACC 协同式自适应巡航模型 搭建四辆车在carsim和simulink进行协同式自适应巡航
  3. ArcBlock ⑩ 月报 | ABT 节点承载运行所有 ArcBlock 产品与服务
  4. 智能汽车「数据合规」进入深水区,背后的盲点和难点
  5. 信息与通信工程学科面试——线性代数
  6. 移动应用程序和网页应用程序_设计移动应用程序的提示
  7. 插入u盘后显示驱动有问题,应该如何修复文件太大无法拷贝到u盘
  8. 实现美食杰的一点点记录
  9. 最近在看些远程办公的机会
  10. linux下的用户 | 新建和删除一个普通用户 | 普通用户和root用户之间的来回切换