MyBatis——缓存

news/2025/1/11 19:52:12/

是一种临时存储少量数据至内存或者是磁盘的一种技术.减少数据的加载次数,可以降低工作量,提高程序响应速度

缓存的重要性是不言而喻的。mybatis的缓存将相同查询条件的SQL语句执行一遍后所得到的结果存在内存或者某种缓存介质当中,当下次遇到一模一样的查询SQL时候不在执行SQL与数据库交互,而是直接从缓存中获取结果,减少服务器的压力;尤其是在查询越多、缓存命中率越高的情况下,使用缓存对性能的提高更明显。

MyBatis允许使用缓存,缓存一般放置在高速读/写的存储器上,比如服务器的内存,能够有效的提供系统性能。MyBatis分为一级缓存和二级缓存,同时也可配置关于缓存设置。

一级存储是SqlSession上的缓存,二级缓存是在SqlSessionFactory(namespace)上的缓存。默认情况下,MyBatis开启一级缓存,没有开启二级缓存。当数据量大的时候可以借助一些第三方缓存框架或Redis缓存来协助保存Mybatis的二级缓存数据。

1.一级缓存

一级存储是SqlSession上的缓存,默认开启,是一种内存型缓存,不要求实体类对象实现Serializable接口。

缓存中的数据使用键值对形式存储数据

namespace+sqlid+args+offset>>> hash值作为键,查询出的结果作为值

@Test
public void testFindDeptByDetpno()   {EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);Emp emp = mapper.findByEmpno(7521);System.out.println(emp);// 中间发生了增删改或者是调用了SqlSession调用了commit,会自动清空缓存sqlSession.commit();// 增删改的时候调用EmpMapper mapper2 = sqlSession.getMapper(EmpMapper.class);Emp emp2 = mapper2.findByEmpno(7521);System.out.println(emp2);System.out.println(emp==emp2);System.out.println(mapper==mapper2);
}

2.二级缓存

二级缓存是以namespace为标记的缓存,可以是由一个SqlSessionFactory创建的SqlSession之间共享缓存数据。默认并不开启。下面的代码中创建了两个SqlSession,执行相同的SQL语句,尝试让第二个SqlSession使用第一个SqlSession查询后缓存的数据。要求实体类必须实现序列化接口

接口

public interface EmpMapper {Emp findByEmpno(int empno);
}

映射文件

<mapper namespace="com.msb.mapper.EmpMapper"><cache/><select id="findByEmpno" resultType="emp" useCache="true" flushCache="false">select * from emp where empno =#{empno}</select></mapper>

测试代码

package com.msb.test;import com.msb.mapper.EmpMapper;
import com.msb.pojo.Emp;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
public class Test3 {private SqlSession sqlSession;private SqlSession sqlSession2;@Beforepublic void init(){SqlSessionFactoryBuilder ssfb =new SqlSessionFactoryBuilder();InputStream resourceAsStream = null;try {resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");} catch (IOException e) {e.printStackTrace();}SqlSessionFactory factory=ssfb.build(resourceAsStream) ;sqlSession=factory.openSession();sqlSession2=factory.openSession();}@Testpublic void testFindDeptByDetpno()   {EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);Emp emp = mapper.findByEmpno(7521);System.out.println(emp);// SqlSession提交之后,才会将查询的结果放入二级缓存sqlSession.commit();EmpMapper mapper2 = sqlSession2.getMapper(EmpMapper.class);Emp emp2 = mapper2.findByEmpno(7521);System.out.println(emp2);}@Afterpublic void release(){// 关闭SQLSessionsqlSession.close();sqlSession2.close();}}

注意其中的commit(),执行该命令后才会将该SqlSession的查询结果从一级缓存中放入二级缓存,供其他SqlSession使用。另外执行SqlSession的close()也会将该SqlSession的查询结果从一级缓存中放入二级缓存。两种方式区别在当前SqlSession是否关闭了。

执行结果显示进行了两次对数据库的SQL查询,说明二级缓存并没有开启。需要进行如下步骤完成开启。

1) 全局开关:在sqlMapConfig.xml文件中的<settings>标签配置开启二级缓存

<settings><setting name="cacheEnabled" value="true"/>
</settings>

cacheEnabled的默认值就是true,所以这步的设置可以省略。

2) 分开关:在要开启二级缓存的mapper文件中开启缓存:

<mapper namespace="com.msb.mapper.EmployeeMapper"><cache/>
</mapper>

3) 二级缓存未必完全使用内存,有可能占用硬盘存储,缓存中存储的JavaBean对象必须实现序列化接口,

public class Emp implements  Serializable {  }

经过设置后,查询结果如图所示。发现第一个SqlSession会首先去二级缓存中查找,如果不存在,就查询数据库,commit()或者close()的时候将数据放入到二级缓存。第二个SqlSession执行相同SQL语句查询时就直接从二级缓存中获取了。

注意:

1) MyBatis的二级缓存的缓存介质有多种多样,而并不一定是在内存中,所以需要对JavaBean对象实现序列化接口。

2) 二级缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响

3) 加入Cache元素后,会对相应命名空间所有的select元素查询结果进行缓存,而其中的insert、update、delete在操作是会清空整个namespace的缓存。

4) cache 有一些可选的属性 type, eviction, flushInterval, size, readOnly, blocking。

<cache type="" readOnly="" eviction=""flushInterval=""size=""blocking=""/>

5) 如果在加入Cache元素的前提下让个别select 元素不使用缓存,可以使用useCache属性,设置为false。useCache控制当前sql语句是否启用缓存 flushCache控制当前sql执行一次后是否刷新缓存

<select id="findByEmpno" resultType="emp" useCache="true" flushCache="false">

http://www.ppmy.cn/news/129889.html

相关文章

二维我的世界源代码(c++)免费复制

这几天整了一个二维我的世界的源代码 累死我了 &#xff08;跪求赞和评论&#xff01;&#xff01;&#xff09; &#xff08;跪求赞和评论&#xff01;&#xff01;&#xff09; &#xff08;跪求赞和评论&#xff01;&#xff01;&#xff09; 小的做东西真的不容易&…

Spring Boot 集成Kafka简单应用

说明&#xff1a;当前kafka的版本为2.13-2.8.1&#xff0c;Spring Boot的版本为2.7.6。 第一步&#xff1a;在pom.xml中引入下述依赖 <dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId><ver…

算命全+冲害关系

<?php $znew paipan(); echo json_encode($z->fatemaps($xb, $yy, $mm, $dd, $hh, $mt 0, $ss 0)); /*** author hkargv139.com* 此日历转换及排盘类完全源于 */ class paipan{/*** 四柱是否区分 早晚子 时,true则23:00-24:00算成上一天*/public $zwz true;/*** 均…

CRNN-基于序列的(端到端)图像文本识别

文章目录 一、前言二、网络架构2.1 特征序列提取2.2. 序列标注2.3. 转录2.3.1 标签序列的概率2.3.2 无字典转录2.3.3 基于词典的转录 2.4. 网络训练4. 总结 一、前言 在现实世界中&#xff0c;稳定的视觉对象&#xff0c;如场景文字&#xff0c;手写字符和乐谱&#xff0c;往往…

Minio 搭建对象存储服务

文章目录 1 mino简介2 环境3 部署3.1 获取程序3.2 存储类别3.3 挂载硬盘3.4 单机部署3.4.1 部署及测试3.4.2 作为Linux Service启动 3.5 分布式集群扩容方案3.5.1 部署及测试3.5.2 作为Linux Service启动 3.6 多机部署&#xff0c;扩容支持 4 客户端及演示5 PrometheusGrafana …

「LSTM 之父」亲笔万字长文,只为向世人证明:深度学习不是在母语为英语的地方被发明的

导语&#xff1a;最重要的并不是谁发明了某项技术&#xff0c;而是技术本身对于人类文明发展所具有的无上价值&#xff01; 雷锋网 AI 科技评论按&#xff1a;毫无疑问&#xff0c;深度学习是影响当今世界科技发展的最重要的技术之一。2018 年&#xff0c;深度学习「三巨头」因…

「LSTM 之父」亲笔万字长文,只为向世人证明:深度学习不是在母语为英语的地方被发明的...

AI科技评论整理 作者&#xff1a;Jrgen Schmidhuber 编译&#xff1a;MrBear 毫无疑问&#xff0c;深度学习是影响当今世界科技发展的最重要的技术之一。2018 年&#xff0c;深度学习「三巨头」因其在这个领域的卓越贡献荣获图灵奖。在人们感慨人工智能迎来春天的同时&#xff…

​Aruba 无线控制器本地账号登录密码重置

Aruba无线控制器现在在运行的版本分为6.x.x.x 和 8.x.x.x两个大版本&#xff0c;版本的区别这里不做介绍&#xff0c;以后有时间再慢慢来写。这里只介绍怎么在无线控制器不重启的情况下恢复本地账号登录密码&#xff0c;无线控制器的运行版本为8.x.x.x。 因为Aruba无线控制器在…