当前位置: 首页 > news >正文

Mybatis缓存

一、什么是缓存

1.什么是缓存

  • 存储在内存当中的数据
  • 将用户常使用的数据存放在缓存(内存)当中,用户查询数据就不用从磁盘(关系型数据库文件)当中查询,从缓存当中查询,从而提高查询效率,解决了高并发系统的性能问题

2.为什么使用缓存

  • 减少和数据库的交互次数,减少系统开销,提高系统效率

3.什么样的数据能使用缓存

  • 经常查询并且不常改变的数据

二、Mybatis缓存

  • mybatis包含了一个非常强大的查询缓存特性,他可以非常方便的定制和配置缓存。缓存可以极大的提高查询的效率
  • mybatis系统当中默认定义了两级缓存:一级缓存和二级缓存
    • 默认情况之下,只有一级缓存开启(sqlSession级别的缓存)
    • 二级缓存需要手动开启配置,需要局域namespace级别的缓存。

1.一级缓存

1.一级缓存也叫本地缓存

    • 与数据库同一次会话期间查询到的数据会放入的本地缓存当中。
    • 如果以后需要获取相同的数据直接去缓存当中拿,没必要再去查询数据库

0

2.测试一级缓存

public class UserTest {private InputStream in = null;private SqlSession session = null;private UserDao mapper = null;/*** 测试查询所有的方法*/@Testpublic void findById() throws IOException {//加载主配置文件,目的是为了构建SqlSessionFactory对象in = Resources.getResourceAsStream("SqlMapConfig.xml");//创建SqlSessionFactory对象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);//通过SqlSessionFactory工厂对象创建SqlSesssion对象session = factory.openSession();//通过Session创建UserDao接口代理对象mapper = session.getMapper(UserDao.class);User user1 = mapper.findById(1);System.out.println(user1.toString());System.out.println("-----------------");User user2 = mapper.findById(1);System.out.println(user2.toString());System.out.println(user1 == user2);//释放资源session.close();in.close();}
}

0

3. 缓存失效的情况

  • sqlSession不同
  • sqlSession相同,查询条件不同
  • sqlSession相同,两次查询之间执行了增删改操作!
  • sqlSession相同,手动清除一级缓存

1.sqlSession不同

0

0

2.sqlSession相同,查询条件不同,多次查询不同的情况,不会导致缓存失效

0

0

3.sqlSession相同,两次查询之间执行了增删改操作!

0

0

4.sqlSession相同,手动清除一级缓存

0

0

2.二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactroy创建SqlSession查询结果会被缓存;此后若再次执行相同的查询语句,结果会从一个缓存中获取。

(1).二级缓存开启的条件

①:在核心配置文件中,设置全局属性caheEnable="true"。

②:在映射件中置

③:查询数据所转换的实体类类型必须实现序列化接口

④:二级缓存必须在SqlSession关闭或提交之后有效

(2).二级缓存失效的情况

两次查询之间行了任意的增删改,会使得一级二级缓存同时失效

(3).开启二级缓存

①.在SqlMapConfig.xml配置文件中开启二级缓存

<!‐‐ 开启二级缓存 ‐‐>
<settings><!--开启二级缓存--><setting name="cacheEnabled" value="true"/>
</settings>

②. 在UserDao.xml配置文件声明使用二级缓存

<!--使用二级缓存-->
<cache/>

③:查询数据所转换的实体类类型必须实现序列化接口

public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;// get set方法 .....}

④:二级缓存必须在SqlSession关闭或提交之后有效

@Test
public void findById() throws IOException {// 1.加载SqlMapConfig配置文件InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建sqlSessionFactory工厂SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);//3.sqlSessionFactory创建sqlSessionSqlSession sqlSession = factory.openSession();SqlSession sqlSession2 = factory.openSession();//4.通过Session创建UserDao接口代理对象UserDao mapper = sqlSession.getMapper(UserDao.class);User user1 = mapper.findById(1);System.out.println(user1.toString());// 将其一级缓存的数据放进二级缓存中,并清空一级缓存sqlSession.close();System.out.println("-----------------");UserDao mapper2 = sqlSession2.getMapper(UserDao.class);User user2 = mapper2.findById(1);System.out.println(user2.toString());// 将其一级缓存的数据放进二级缓存中,并清空一级缓存sqlSession2.close();System.out.println(user1 == user2);resourceAsStream.close();
}

测试结果

0

(4).重要结论

0

打印发现2个对象的地址值不一样,但是确实只发送了一次SQL语句的查询,二级缓存中存储的是数据,不是对象。

(5).Catch参数的具体细节

eviction(收回策略)

  • LRU(最近最少使用的):移除最长时间不被使用的对象,这是默认值。
  • FIFO(先进先出):按对象进入缓存的顺序来移除它们。
  • SOFT(软引用):移除基于垃圾回收器状态和软引用规则的对象。
  • WEAK(弱引用):更积极地移除基于垃圾收集器状态和弱引用规则的对象。

flushinterval(刷新间隔) 可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。

  • 默认情况不设置,即没有刷新间隔,缓存仅仅在调用语句时刷新。

size(引用数目)

  • 可以被设置为任意正整数,要记住缓存的对象数目和运行环境的可用内存资源数目。默认值是1024 。

readOnly(只读) 属性可以被设置为 true / false。

    • true:只读缓存:会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改, 这提供了很重要的性能优势。
    • false读写缓存: 通过序列化返回缓存对象的拷贝,这种方式会慢一些,但是安全,因此默认是 false。

配置结果

<cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>

三、Mybatis缓存查询顺序

  • 先查询二级缓存,因为二级缓存中可能会有其他程序查询出来的数据,可以直接拿来使用
  • 如果二级缓存未命中,再查询一级缓存
  • 如果一级缓存也没有命中,则查询数据库
  • SqlSession关闭之后,一级缓存的数据会写入二级缓存

0


http://www.mrgr.cn/news/62342.html

相关文章:

  • 浅谈在大厂工作期间QA在测试中应知应做
  • Spring 设计模式之装饰器模式
  • 五连杆VMC
  • ios 快捷指令扩展(Intents Extension)简单使用 swift语言
  • Labview写CIP协议
  • 【JVM第1课】Java 跨平台原理
  • 四足机器人实战篇之十:cheetah mini运动控制工程解读(附C++代码)
  • JAVA——多线程
  • JAVA程序导致cpu标高排查
  • 微服务设计模式 — 补偿事务模式(Compensating Transaction Pattern)
  • 基于java+SpringBoot+Vue的网上租贸系统设计与实现
  • Java8中CompletableFuture.allOf的使用
  • Python飞舞蝙蝠
  • 迪杰斯特拉算法(Dijkstra‘s Algorithm
  • Vue学习记录之二十七 Pinia的使用
  • 97、Python并发编程:多线程实现的两种方式
  • 串口屏控制的自动滑轨
  • 【MySQL】 运维篇—安全管理:数据加密与SSL配置
  • Java基础2-数组
  • Python | Leetcode Python题解之第521题最长特殊序列I
  • C语言 | Leetcode C语言题解之第522题最长特殊序列II
  • C++ | Leetcode C++题解之第522题最长特殊序列II
  • 【多线程场景下事务失效问题如何处理?】
  • 从openjdk17 C++源码角度看 java类成员变量是怎么赋值的
  • 理解环境变量与Shell编程:Linux开发的基础
  • DS18B20+测量系统可编程分辨率高精度数字温度传感器芯片