河北爱站网络科技有限公司,wordpress 文章图片自动添加,江苏建站速度忿,域名所有人是网站名不能转出前言
为什么要学习Mybatis 缓存机制#xff1f;
学习Mybatis 缓存机制#xff0c;可以有效解决 数据库的压力#xff0c;提高数据库的性能。
例如#xff1a;你要 对tb_user 表 #xff0c;查询 所有用户的信息,并且多次查询所有用户信息。我们知道第一次查询表信息流…前言
为什么要学习Mybatis 缓存机制
学习Mybatis 缓存机制可以有效解决 数据库的压力提高数据库的性能。
例如你要 对tb_user 表 查询 所有用户的信息,并且多次查询所有用户信息。我们知道第一次查询表信息流程是 执行 sql 查询语句找到存储在数据库的目标数据【在硬盘】最后得到这些数据。那如果第二次查询我们依旧如此这般循环往复如果是存储很多数据的数据库这样一次查询耗时是很长的且会数据库的性能。
思考当 第一次得到查询数据或者进行其他的操作后能否把最终的数据临时存储在一个地方。当第二次执行相同的sql 语句时传递相同的参数,可以直接从这地方获得不再需要从 数据库进行二次查询。这样不仅节省了时间还提高了性能。-------Mybatis 缓存机制 的功能 Mybatis一级缓存
一级缓存的功能
一级缓存会将第一次执行SQL语句后查询到的结果存储在缓存中。这些数据会被暂存以便后续的查询操作可以直接从缓存中读取而无需再次访问数据库。
一级缓存 是SqlSession 级别的缓存。如果同一个SqlSession 对象 多次执行完全相同的sql 语句在第一次执行完成后 Mybatis 会将查询结果写入一级缓存中此后如果程序没有执行插入更新删除操作当第二次执行相同的查询语句Mybatis 会直接 读取一级缓存中的数据而不用再去数据库查询从而提高数据库的查询效率。
例子
从 数据表 tb_book 中多次 查询 di1 的图书信息使用 一级缓存 。 注意学习 一级缓存的核心 不仅仅理解 一级缓存是临时存储场所而且始终与数据库存储的数据保持同步------这里具体表现为数据的一致性 数据一致性的真正含义
数据一致性是指在缓存机制中缓存中的数据与数据库中的数据始终保持一致。具体来说这意味着 读取操作当从缓存中读取数据时缓存中的数据必须是最新的与数据库中的数据完全一致。 写入操作当数据库中的数据发生变化时例如通过INSERT、UPDATE、DELETE操作缓存中的数据必须及时更新或失效以避免读取到过时的数据。 验证 数据的一致性 1 当执行相同的sql 语句时获得相同的结果 2 存储在 一级缓存的数据在数据库中也要存在并且不会轻易被改变 demo(案例验证 数据的一致性 目的 查询 id1 时图书信息 项目准备
tb_book 表 和与之对应的 实体类 Book 类
tb_book 表 实体类 Book 类 添加 需要的依赖
mybatis 框架固定的依赖 log4j 日志依赖 通过控制台直观看到整个过程 dependencies!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.6/version/dependency!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.16/version/dependency!-- https://mvnrepository.com/artifact/log4j/log4j --dependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion1.2.17/version/dependency/dependencies
和log4j 日志依赖配套的log4j.properties 配置文件
# Set root logger level
log4j.rootLoggerDEBUG, stdout# Set the log output format
log4j.appender.stdoutorg.apache.log4j.ConsoleAppender
log4j.appender.stdout.layoutorg.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n BookMapper 接口方法 // 根据id查询图书public Book queryBookById(int id);// 更新图书public int updateBook(Book book); 正文
BookMapper.xml 映射文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacefs.mapper.BookMapper
!-- 根据id 查询 图书信息--select idqueryBookById parameterTypeint resultTypefs.entity.Bookselect * from tb_book where id #{id}/select
!-- 根据id 修改--update idupdateBook parameterTypefs.entity.Bookupdate tb_book set price #{price},author #{author},bookName #{bookName} where id #{id}/update
/mapper BookTest 测试类
1 两次查询 id1 时图书信息 // 第一次执行Book book sqlSession.selectOne(queryBookById, 1);System.out.println(book);// 第二次执行 sqlSession.selectOne(queryBookById, 1);Book book1 sqlSession.selectOne(queryBookById, 1);System.out.println(book1);
运行截图 发现 通过运行截图和 代码发现之后使用同样的sql 语句和传递相同的参数会从一级缓存中直接获得不再经过数据库。 2 查询id1 和第二次 id2 图书信息
BookTest 测试类 运行截图 发现 即使第二次执行相同的sql 语句如果传递不同的参数不能从一级缓存中获得目标结果只能通过数据库查询 3 第一次执行 id1 的查询 图书信息 第二次执行 修改 id1 的图书名第三次查询id1图书信息
BookTest 测试类 // 第一次执行Book book sqlSession.selectOne(queryBookById, 1);System.out.println(book);// 第二次更新int update sqlSession.update(updateBook, new Book(1, author, Html基础,67));sqlSession.commit();// 第二次执行 sqlSession.selectOne(queryBookById, 1);Book book1 sqlSession.selectOne(queryBookById, 1);System.out.println(book1);sqlSession.close();
运行截图 最后我们发现 一级缓存实质上是在内存开辟一个空间来存储数据的。 一级缓存不需要我们手动创建或者设置的 Mybatis二级缓存
为什么要学习 Mybatis二级缓存 学完一级缓存后发现 在相同的Mapper 映射文件中使用相同的SQL语句如果sqlSession不同则两个sqlSession查询数据时会查询数据两次这样会降低数据库的查询效率。因此为了解决这个问题 使用 Mybatis二级缓存 Mybatis二级缓存 的优点 二级缓存 是一个跨多个 SqlSession 的共享缓存机制它的作用范围比一级缓存更广泛。二级缓存可以显著提高系统的性能因为它允许在多个会话之间共享缓存数据从而减少对数据库的重复查询。 二级缓存的工作原理 查询流程 当执行查询操作时MyBatis 首先检查一级缓存。 如果一级缓存中没有找到数据则检查二级缓存。 如果二级缓存中也没有找到数据则查询数据库并将结果存入二级缓存。 更新流程 当执行数据更新操作如 INSERT、UPDATE、DELETE时MyBatis 会清空相关的一级缓存和二级缓存以确保数据一致性。 手动打开二级缓存的步骤
1 在主配置文件 mybatis-config .xml 开启二级 缓存的全局配置 settings
!-- 开启日志--setting namelogImpl valueLOG4J/
!-- 开启二级缓存--setting namecacheEnabled valuetrue/
/settings 2 在 Mapper XML 文件中使用 cache 标签配置二级缓存。 二级缓存一般是默认状态可以实现的功能如下 1 映射文件所有的select 语句将会被缓存 2 映射文件中的所有的insertupdatedelete 都会被刷新缓存 3 缓存会使用LRU算法回收 4 没有刷新间隔 5 缓存是可读可写的但不被共享 以上是默认状态的特性如果需要调整可通过cache 元素的属性来实现
配置参数说明 eviction缓存回收策略。可选值包括 FIFO先进先出 LRU最近最少使用 SOFT软引用 WEAK弱引用 flushInterval缓存刷新间隔毫秒。默认值为不刷新。 size缓存的最大存储对象数量。 readOnly是否只读。如果设置为 true则缓存中的数据被认为是只读的可以提高性能但不允许修改。 3 . 实体类实现 Serializable 4 BookTest测试类中 两次查询 id1 的图书信息
package fs.Test;import fs.entity.Book;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;public class BookTest {public static void main(String[] args) throws IOException {InputStream resource Resources.getResourceAsStream(mybatis-confif.xml);SqlSessionFactory build new SqlSessionFactoryBuilder().build(resource);SqlSession sqlSession build.openSession();SqlSession sqlSession1 build.openSession();// 第一次执行Book book sqlSession.selectOne(queryBookById, 3);System.out.println(book);sqlSession.close();// 第二次执行Book book1 sqlSession1.selectOne(queryBookById, 3);System.out.println(book1);sqlSession1.close();}
}运行截图 补充
缓存命中率 缓存命中率的计算公式 缓存命中率通常通过以下公式计算 缓存命中率总查询次数缓存命中次数 缓存命中次数从缓存中成功获取到数据的次数。 总查询次数所有查询操作的次数包括从缓存中获取数据和从数据库中查询数据的次数。 示例 假设你进行了 10 次查询操作 3 次查询直接从缓存中获取到了数据缓存命中。 7 次查询需要从数据库中查询数据缓存未命中。 那么缓存命中率为 缓存命中率1030.3 或 30% MyBatis 中的缓存命中率 在 MyBatis 的日志中你可以看到类似以下的输出 DEBUG BookMapper:60 - Cache Hit Ratio [fs.mapper.BookMapper]: 0.0 这表示当前的缓存命中率为 0.0即尚未有缓存命中。 为什么缓存命中率是 0.0 缓存尚未生效 如果是第一次查询缓存尚未填充因此命中率为 0。 如果二级缓存未正确配置如实体类未实现 Serializable 接口或 cache 标签未正确设置缓存可能不会生效。 查询条件不匹配 缓存基于查询语句和参数进行匹配。如果查询语句或参数不同即使使用了缓存也可能无法命中。 缓存被清空 如果在两次查询之间执行了数据更新操作如 INSERT、UPDATE、DELETE二级缓存可能会被清空导致命中率为 0。