MyBatis一级缓存、二级缓存

一、MyBatis一级缓存

MyBatis默认启动一级缓存,一级缓存是SqlSession级别的

注意:有两个因素会使一级缓存失效
  1.对SqlSession进行commit()操作(即对数据库进行了增、删、改操作)。数据库中的数据发生了改变,此时若再从内存中读取缓存的数据,则会读取到错误的数据信息,所以此时旧的一级缓存中的数据会清空,当用户下一次执行查询操作时,

会重新从数据库中读取数据并放入一级缓存中
  2.关闭SqlSession。一级缓存的设计是每个sqlsession单独使用一个缓存空间,不同的sqlsession是不能互相访问数据的。当然,在SqlSession关闭后,其中数据自然被清空。由此可以看出,一级缓存是SqlSession级别的

 测试一:

第一次查询时ID为2,第二次ID为3,第三次查询时ID又为3,运行程序,通过log4j日志得知,获得了3个结果,但是ID为2的SQL语句只执行了一次,第二次ID为2的SQL语句与第一次相同,直接从缓存中获取结果,而没有再次执行id=2的SQL语句。

SqlSession sqlSession1=DbUtil.getSqlSession();     //这里自己编写了一个DbUtil工具类,其下有一个getSqlSession()的静态方法,由SqlSessionFactory的openSession()方法获得并返回一个SqlSession对象
    UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class);

  System.out.println(userMapper1.findUserById(2));  //findUserById(int id)是UserMapper接口中的方法

System.out.println(userMapper1.findUserById(3));

  System.out.println(userMapper1.findUserById(2));

 测试二:

sqlSession1.close();/**一旦关闭了sqlSession1,开启一个新的sqlSession2,那么sqlSession1的一级缓存失效,相同的ID为2的查询语句本次也会执行,在日志记录中会看到执行了两次select*from users where user_id=2的语句**/
    SqlSession sqlSession2=DbUtil.getSqlSession();
    UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
    System.out.println(userMapper2.findUserById(2));

二、MyBatis二级缓存

一级缓存的作用域仅限于一个sqlsession,而二级缓存的作用域是一个namespace。但并不是意味着同一个namespace创建的mapper可以互相读取缓存内容,

这里的原则是,如果开启了二级缓存,那么在关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。

开启二级缓存的步骤:

1.打开二级缓存总开关
打开总开关,只需要在mybatis总配置文件中加入一行设置

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

2.打开需要使用二级缓存的mapper的开关

在需要开启二级缓存的mapper.xml(比如UserMapper.xml)中加入caceh标签

<cache/>

3.POJO序列化

让需要使用二级缓存的POJO类实现Serializable接口,如

public class User implements Serializable {}

在开启二级缓存之后,再次执行之前测试中的代码,会发现即使sqlSession1.close()之后,再重新获得新的SqlSession sqlSession2=DbUtil.getSqlSession(),然后再次执行相同的SQL操作,查询ID为2的用户,如下:    UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);    System.out.println(userMapper2.findUserById(2));最终会发现在日志记录中只执行了一次select*from users where user_id=2的语句,证明二级缓存开启成功!

必须注意的是:即使开启了二级缓存,不同的sqlsession之间的缓存数据也不是想互访就能互访的,必须等到sqlsession关闭了以后,才会把其一级缓存中的数据写入二级缓存如果把之前的sqlSession1.close()注释掉,那么同样会执行两次select*from users where user_id=2的SQL语句,因为sqlSession1没有关闭,一级缓存中的数据并没写入二级缓存,而sqlSession2又无法访问sqlSession1的一级缓存中的数据,所以会重新执行该查询语句。
时间: 2024-08-26 17:09:21

MyBatis一级缓存、二级缓存的相关文章

Mybatis一级、二级缓存

一级缓存 首先做一个测试,创建一个mapper配置文件和mapper接口,我这里用了最简单的查询来演示. <mapper namespace="cn.elinzhou.mybatisTest.mapper.UserMapper"> <select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User"> SELECT * FROM user </se

【MyBatis学习13】MyBatis中的二级缓存

1. 二级缓存的原理 前面介绍了,mybatis中的二级缓存是mapper级别的缓存,值得注意的是,不同的mapper都有一个二级缓存,也就是说,不同的mapper之间的二级缓存是互不影响的.为了更加清楚的描述二级缓存,先来看一个示意图: 从图中可以看出: sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到该UserMapper的二级缓存中. 如果SqlSession3去执行相同 mapper下sql,执行commit提交,则会清空该UserMapper下二级缓

Mybatis学习笔记-二级缓存

~ 缓存是提供应用系统性能的重要手段,前面已经介绍过Mybatis是一级缓存,与一级缓存不同的是,二级缓存的作用范围扩大到了应用级别,并且可以比一级缓存更细粒度的对二级缓存的应用进行配置.下面就详细叙述一下Mybatis的二级缓存实现. 二级缓存的工作流程 不多说,先上图,图解是攻城狮最好的朋友^_^- 前面在叙述一级缓存的时候已经说过,一级缓存是一块放在Executor中的map内存块.试想一下,如果二级缓存也是Executor中的内存块可以可以呢?-- 当然不可以!为啥?因为二级缓存要支持细

Mybatis自定义分布式二级缓存实现与遇到的一些问题解决方案!

先说两句: 我们都知道Mybatis缓存分两类: 一级缓存(同一个Session会话内) & 二级缓存(基于HashMap实现的以 namespace为范围的缓存) 今天呢, 我们不谈一级缓存, 我们来谈一谈 二级缓存, 通过查看Mybatis源码发现, 他的二级缓存实现真的十分简单, 默认的实现类是 org.apache.ibatis.cache.impl.PerpetualCache 这里贴一下他的源码吧: /** * Copyright 2009-2015 the original aut

【Hibernate】一级、二级缓存

本文讲述HIbernate中一级.二级缓存的概念以及如何使用. 一.大纲 2.什么是一级缓存 3.一级缓存示例展示 4.二级缓存以及示例展示 5.总结 二.什么是一级缓存 在hibernate中所谓的一级缓存就是session对象,但是一级缓存对提高性能的作用性并不是很大,其session主要的目的是管理实体对象的状态(临时.离线.持久化). 其缓存模型如下图: 三.一级缓存示例 3.1 查询(get,load, HQL) 3.1.1 get/load方法 @Test public void t

Mybatis使用Redis二级缓存

在Mybatis中允许开发者自定义自己的缓存,本文将使用Redis作为Mybatis的二级缓存.在Mybatis中定义二级缓存,需要如下配置: 1. MyBatis支持二级缓存的总开关:全局配置变量参数“cacheEnabled=true” 2.select语句所在的Mapper需配置了<cache> 或<cached-ref>节点 3.select语句的参数 useCache=true Mybatis配置文件如下: <settings> <!-- 这个配置使全局

hibernate的一级和二级缓存

一级缓存就是Session级别的缓存,close后就没了. 二级缓存就是SessionFactory级别的缓存,全局缓存,要配置其他插件. 什么样的数据适合存放到第二级缓存中? 1.很少被修改的数据 2.不是很重要的数据,允许出现偶尔并发的数据 3.不会被并发访问的数据 4.参考数据 不适合存放到第二级缓存的数据? 1.经常被修改的数据 2.财务数据,绝对不允许出现并发 3.与其他应用共享的数据.         Hibernate的二级缓存策略的一般过程如下: 1) 条件查询的时候,总是发出一

SpringBoot+Mybatis+redis实现二级缓存

对于查询比较多的项目可以考虑配置二级缓存,mybatis本身的二级缓存是缓存到本地,但是对于多个节点的项目来说,可能会出现数据不一致的问题,所以采用redis缓存,这样二级缓存的数据就可以缓存到内存,可实现多个节点项目的数据同步. 1.配置redis的连接 #redis gmall.redis.host=172.16.1.250 gmall.redis.port=6379 gmall.redis.pass=Gworld2017 gmall.redis.photo.database=6 #最大分配

hibernate的获取session的两方法比较,和通过id获取对象的比较,一级缓存二级缓存

opensession与currentsession的联系与区别 在同一个线程中opensession的session是不一样的,而currentsession获取的session是一样的,这就保证了线程的安全性.当然想要后者的session需要在配置文件中手动配置,另外我们可以写一个工具类来获得后者的session. get vs load 如果查询不到数据,get会会返回null但是不会报错 若果load查询不到数据,则会报错 get立即向db发送请求 ,如果你使用的是load查询数据,即使

mybatis学习--缓存(一级和二级缓存)

声明:学习摘要! MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相同的查询语句,完全可以把查询结果存储起来,下次查询同样的内容的时候直接从内存中获取数据即可,这样在某些场景下可以大大提升查询效率. MyBatis的缓存分为两种: 一级缓存,一级缓存是SqlSession级别的缓存,对于相同的查询,会从缓存中返回结果而不是查询数据库 二级缓存,二级