【Mybatis】缓存
1、什么是缓存Cache ?
存在内存中的临时数据。
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
2、为什么使用缓存?
减少和数据库的交互次数,减少系统开销,提高系统效率。
3、什么样的数据能使用缓存?
经常查询并且不经常改变的数据。
Mybatis缓存
MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
一级缓存
一级缓存也叫本地缓存:
与数据库同一次会话期间查询到的数据会放在本地缓存中。
以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
一级缓存失效的四种情况
一级缓存是SqlSession级别的缓存,是一直开启的,我们关闭不了它;
一级缓存失效情况:没有使用到当前的一级缓存,效果就是,还需要再向数据库中发起一次查询请求!
1、sqlSession不同
2、sqlSession相同,查询条件不同
3、sqlSession相同,两次查询之间执行了增删改操作!
4、sqlSession相同,手动清除一级缓存
二级缓存
二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
工作机制
一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
新的会话查询信息,就可以从二级缓存中获取内容;
不同的mapper查出的数据会放在自己对应的缓存(map)中;
实例
【注】:本实例基于【Mybatis】Map传参和模糊查询
1. 默认情况下开启一级缓存
(1)同一个SqlSession中执行相同的查询。
执行以下代码,会发现sql语句只执行了一次(第二次查询是在缓存中取出的)。
@Testpublic void getUserById(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);System.out.println(mapper.getUserById(2));System.out.println("----------------------------------------");System.out.println(mapper.getUserById(2));sqlSession.close();}
运行结果:
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1634723627.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@616fe72b]
==> Preparing: select * from user where id = ?
==> Parameters: 2(Integer)
<== Columns: id, name, pwd
<== Row: 2, user02, 123456
<== Total: 1
User{id=2, name='user02', pwd='123456'}
----------------------------------------
User{id=2, name='user02', pwd='123456'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@616fe72b]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@616fe72b]
Returned connection 1634723627 to pool.
(2)不同SqlSession执行相同的查询。
@Testpublic void getUserById(){// 第一个SqlSessionSqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);System.out.println(mapper.getUserById(2));System.out.println("----------------------------------------");sqlSession.close();// 第二个SqlSessionSqlSession sqlSession2 = MybatisUtils.getSqlSession();UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);System.out.println(mapper2.getUserById(2));sqlSession2.close();}
运行结果:可以发现执行了两次数据库查询。
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 2120063568.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7e5d9a50]
==> Preparing: select * from user where id = ?
==> Parameters: 2(Integer)
<== Columns: id, name, pwd
<== Row: 2, user02, 123456
<== Total: 1
User{id=2, name='user02', pwd='123456'}
----------------------------------------
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7e5d9a50]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7e5d9a50]
Returned connection 2120063568 to pool.
Opening JDBC Connection
Checked out connection 2120063568 from pool.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7e5d9a50]
==> Preparing: select * from user where id = ?
==> Parameters: 2(Integer)
<== Columns: id, name, pwd
<== Row: 2, user02, 123456
<== Total: 1
User{id=2, name='user02', pwd='123456'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7e5d9a50]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7e5d9a50]
Returned connection 2120063568 to pool.
2. 手动开启二级缓存。
在UserMapper.xml中加入<cache/>,如下:
再次执行代码:
@Testpublic void getUserById(){// 第一个SqlSessionSqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);System.out.println(mapper.getUserById(2));System.out.println("----------------------------------------");sqlSession.close();// 第二个SqlSessionSqlSession sqlSession2 = MybatisUtils.getSqlSession();UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);System.out.println(mapper2.getUserById(2));sqlSession2.close();}
运行结果:发现只进行了一次数据库查询。
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Cache Hit Ratio [com.company.org.dao.UserMapper]: 0.0
Opening JDBC Connection
Created connection 1019484860.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3cc41abc]
==> Preparing: select * from user where id = ?
==> Parameters: 2(Integer)
<== Columns: id, name, pwd
<== Row: 2, user02, 123456
<== Total: 1
User{id=2, name='user02', pwd='123456'}
----------------------------------------
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3cc41abc]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3cc41abc]
Returned connection 1019484860 to pool.
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.company.org.dao.UserMapper]: 0.5
User{id=2, name='user02', pwd='123456'}
【注】这里运行时可能会报错:
org.apache.ibatis.cache.CacheException: Error serializing object. Cause: java.io.NotSerializableException: com.company.org.pojo.User
解决办法是将User类继承自Serializable:
public class User implements Serializable {......}
3. 测试一下更新对缓存的影响。
@Testpublic void getUserById(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);System.out.println(mapper.getUserById(2));System.out.println("----------------------------------------");// 执行更新mapper.updateUser(new User(4, "ssssssssssssss", "654321"));sqlSession.commit();System.out.println("----------------------------------------");System.out.println(mapper.getUserById(2));sqlSession.close();}
运行结果:执行了两次数据库查询。
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1634723627.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@616fe72b]
==> Preparing: select * from user where id = ?
==> Parameters: 2(Integer)
<== Columns: id, name, pwd
<== Row: 2, user02, 123456
<== Total: 1
User{id=2, name='user02', pwd='123456'}
----------------------------------------
==> Preparing: update user set name = ?, pwd = ? where id = ?
==> Parameters: ssssssssssssss(String), 654321(String), 4(Integer)
<== Updates: 1
Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@616fe72b]
==> Preparing: select * from user where id = ?
==> Parameters: 2(Integer)
<== Columns: id, name, pwd
<== Row: 2, user02, 123456
<== Total: 1
User{id=2, name='user02', pwd='123456'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@616fe72b]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@616fe72b]
Returned connection 1634723627 to pool.
【Mybatis】缓存相关推荐
- MyBatis复习笔记6:MyBatis缓存机制
MyBatis缓存机制 MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.缓存可以极大的提升查询效率. MyBatis系统中默认定义了两级缓存. 一级缓存和二级缓存. 默认情 ...
- 实际测试例子+源码分析的方式解剖MyBatis缓存的概念
前言: 前方高能! 本文内容有点多,通过实际测试例子+源码分析的方式解剖MyBatis缓存的概念,对这方面有兴趣的小伙伴请继续看下去~ 欢迎工作一到五年的Java工程师朋友们加入Java架构开发:79 ...
- Mybatis 缓存系统源码解析
Mybatis 缓存系统源码解析 转载于:https://juejin.im/post/5bfa50905188251d0920006c
- MyBatis学习总结(七)——Mybatis缓存
一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...
- MyBatis(三)MyBatis缓存和工作原理
MyBatis缓存 MyBatis提供了一级缓存和二级缓存,并且预留了集成第三方缓存的接口. 从上面MyBatis的包结构可以很容易看出跟缓存相关的类都在cache的package里,其底层是一个Ca ...
- 后端:MyBatis缓存知识介绍
今天给大家分享一下MyBatis缓存知识介绍,希望对大家日常的开发当中能有所帮助! 一.MyBatis一级缓存 1.一级缓存介绍 当我们的程序MyBatis开启一次和数据库的会话,MyBatis会自动 ...
- MyBatis缓存通俗易懂
1.1 mybatis缓存介绍 如下图,是mybatis一级缓存和二级缓存的区别图解: Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的 ...
- 缓存在哪里_什么是MyBatis缓存技术
MyBatis缓存 引言 在一个Web项目中,查询数据库中的操作算是一个非常常用的操作,但是有些数据会被经常性的查询,而每一次都去数据库中查询这些重复的数据,会很消耗数据库的资源,同时使得查询效率也很 ...
- mybatis缓存二级缓存_MyBatis缓存与Apache Ignite的陷阱
mybatis缓存二级缓存 一周前,MyBatis和Apache ignite 宣布支持apache ignite作为MyBatis缓存(L2缓存). 从技术上讲,MyBatis支持两个级别的缓存: ...
- MyBatis缓存与Apache Ignite的陷阱
一周前,MyBatis和Apache ignite 宣布支持apache ignite作为MyBatis缓存(L2缓存). 从技术上讲,MyBatis支持两个级别的缓存: 本地缓存,默认情况下始终启用 ...
最新文章
- 一、进程的概念、组成和特征
- Atitit.提升api兼容性的方法 v3 q326
- 谁是最好的Coder
- 排序算法-01冒泡排序(Python实现)
- Java自定义JSlider UI
- 11. mysql锁机制_深入探讨MySQL锁机制
- 判断深度学习模型的稳定性_全自动搭建定制化深度学习模型
- ++库 照片风格转换风格_seaborn库:整体风格设置
- CentOS上使用netstat命令查证DDOS***
- Mysql:语法:虚拟表DUAL
- 系统自带不起眼但很强杀毒工具
- win7开启telnet工具
- 目前3个最受欢迎的免费、开源文件加密软件评测
- 博客园9月份第3周51Aspx源码发布详情
- 二级路由dhcp关闭连不上wifi_如何做到让家里WiFi真正全覆盖的几个布线方案
- 产品经理的私房菜 - 腾讯产品模型 - 执行力篇
- 正则匹配里面的(.*?)
- 庆祝鸿蒙指的是哪个生肖,12月中头彩,苦难转幸福,3生肖,鸿蒙紫气,运走上坡路,想啥就有啥...
- 【参赛作品70】MOGDB/openGauss与PostgreSQL关于GDK字符集问题
- Office2016安装报错:1935安装程序集组件发生错误
热门文章
- 接上篇,通过接口实现多态,求三角形,矩形,圆周长面积
- ubuntu离线安装python_Ubuntu离线安装软件包
- 关于hi3516DV300的VDEC一些测试
- 面试积累(String和StringBuffer, StringBuilder的理解)
- 为啥不能用比特币给贪官送礼?
- Nginx实现URL路径转接
- python中from import*的*什么意思_[Python]Python中的import和from import
- 《iOS Drawing Practical UIKit Solutions》读书笔记(四) —— 遮罩,模糊和动画
- 如何修复硬盘坏道(360)
- 初识CityEngine