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】缓存相关推荐

  1. MyBatis复习笔记6:MyBatis缓存机制

    MyBatis缓存机制 MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.缓存可以极大的提升查询效率. MyBatis系统中默认定义了两级缓存. 一级缓存和二级缓存. 默认情 ...

  2. 实际测试例子+源码分析的方式解剖MyBatis缓存的概念

    前言: 前方高能! 本文内容有点多,通过实际测试例子+源码分析的方式解剖MyBatis缓存的概念,对这方面有兴趣的小伙伴请继续看下去~ 欢迎工作一到五年的Java工程师朋友们加入Java架构开发:79 ...

  3. Mybatis 缓存系统源码解析

    Mybatis 缓存系统源码解析 转载于:https://juejin.im/post/5bfa50905188251d0920006c

  4. MyBatis学习总结(七)——Mybatis缓存

    一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...

  5. MyBatis(三)MyBatis缓存和工作原理

    MyBatis缓存 MyBatis提供了一级缓存和二级缓存,并且预留了集成第三方缓存的接口. 从上面MyBatis的包结构可以很容易看出跟缓存相关的类都在cache的package里,其底层是一个Ca ...

  6. 后端:MyBatis缓存知识介绍

    今天给大家分享一下MyBatis缓存知识介绍,希望对大家日常的开发当中能有所帮助! 一.MyBatis一级缓存 1.一级缓存介绍 当我们的程序MyBatis开启一次和数据库的会话,MyBatis会自动 ...

  7. MyBatis缓存通俗易懂

    1.1     mybatis缓存介绍 如下图,是mybatis一级缓存和二级缓存的区别图解: Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的 ...

  8. 缓存在哪里_什么是MyBatis缓存技术

    MyBatis缓存 引言 在一个Web项目中,查询数据库中的操作算是一个非常常用的操作,但是有些数据会被经常性的查询,而每一次都去数据库中查询这些重复的数据,会很消耗数据库的资源,同时使得查询效率也很 ...

  9. mybatis缓存二级缓存_MyBatis缓存与Apache Ignite的陷阱

    mybatis缓存二级缓存 一周前,MyBatis和Apache ignite 宣布支持apache ignite作为MyBatis缓存(L2缓存). 从技术上讲,MyBatis支持两个级别的缓存: ...

  10. MyBatis缓存与Apache Ignite的陷阱

    一周前,MyBatis和Apache ignite 宣布支持apache ignite作为MyBatis缓存(L2缓存). 从技术上讲,MyBatis支持两个级别的缓存: 本地缓存,默认情况下始终启用 ...

最新文章

  1. 一、进程的概念、组成和特征
  2. Atitit.提升api兼容性的方法 v3 q326
  3. 谁是最好的Coder
  4. 排序算法-01冒泡排序(Python实现)
  5. Java自定义JSlider UI
  6. 11. mysql锁机制_深入探讨MySQL锁机制
  7. 判断深度学习模型的稳定性_全自动搭建定制化深度学习模型
  8. ++库 照片风格转换风格_seaborn库:整体风格设置
  9. CentOS上使用netstat命令查证DDOS***
  10. Mysql:语法:虚拟表DUAL
  11. 系统自带不起眼但很强杀毒工具
  12. win7开启telnet工具
  13. 目前3个最受欢迎的免费、开源文件加密软件评测
  14. 博客园9月份第3周51Aspx源码发布详情
  15. 二级路由dhcp关闭连不上wifi_如何做到让家里WiFi真正全覆盖的几个布线方案
  16. 产品经理的私房菜 - 腾讯产品模型 - 执行力篇
  17. 正则匹配里面的(.*?)
  18. 庆祝鸿蒙指的是哪个生肖,12月中头彩,苦难转幸福,3生肖,鸿蒙紫气,运走上坡路,想啥就有啥...
  19. 【参赛作品70】MOGDB/openGauss与PostgreSQL关于GDK字符集问题
  20. Office2016安装报错:1935安装程序集组件发生错误

热门文章

  1. 接上篇,通过接口实现多态,求三角形,矩形,圆周长面积
  2. ubuntu离线安装python_Ubuntu离线安装软件包
  3. 关于hi3516DV300的VDEC一些测试
  4. 面试积累(String和StringBuffer, StringBuilder的理解)
  5. 为啥不能用比特币给贪官送礼?
  6. Nginx实现URL路径转接
  7. python中from import*的*什么意思_[Python]Python中的import和from import
  8. 《iOS Drawing Practical UIKit Solutions》读书笔记(四) —— 遮罩,模糊和动画
  9. 如何修复硬盘坏道(360)
  10. 初识CityEngine