我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JavaMybatis一级缓存和二级缓存

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JavaMybatis一级缓存和二级缓存

一、什么是缓存 

        缓存是内存当中一块存储数据的区域,目的是提高查询效率。MyBatis会将查询结果存储在缓存当中,当下次执行相同的SQL时不访问数据库,而是直接从缓存中获取结果,从而减少服务器的压力。

什么是缓存?

存在于内存中的一块数据。

缓存有什么作用?

减少程序和数据库的交互,提高查询效率,降低服务器和数据库的压力。

什么样的数据使用缓存?

经常查询但不常改变的,改变后对结果影响不大的数据。

MyBatis缓存分为哪几类?

 一级缓存和二级缓存

如何判断两次Sql是相同的?

查询的Sql语句相同 传递的参数值相同 对结果集的要求相同 预编译的模板Id相同

二、Mabtis一级缓存

MyBatis一级缓存也叫本地缓存。SqlSession对象中包含一个Executor对象,Executor对象中包含一个PerpetualCache对象,在该对象存放一级缓存数据。

由于一级缓存是在SqlSession对象中,所以只有使用同一个SqlSession对象操作数据库时才能共享一级缓存。

MyBatis的一级缓存是默认开启的,不需要任何的配置。

如下图所示:

(1)测试一级缓存

其实测试方法很简单,就是通过使用相同和不同的SqlSession对象进行SQL查询,返回的对象的哈希值是否一样就可以知道了,如果返回的哈希值一样说明没有进行SQL查询,而是直接从缓存拿到对象来返回

下面是使用相同的Session对象来执行查询,如果观察user1和user2的哈希值一样则说明确实开启了一级缓存,并没有进行查询,而是直接从缓存中拿数据。 

import com.mybatisstudy.mapper.UserMapper;
import com.mybatisstudy.pojo.User;
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.Test;
 
import java.io.InputStream;
 
public class TestUserMapper3 {
    // 测试使用同一个SqlSession查询
    @Test
    public void testCache1() throws Exception{
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        SqlSession session = factory.openSession();
 
        // 使用同一个SqlSession查询
        UserMapper mapper1 = session.getMapper(UserMapper.class);
        UserMapper mapper2 = session.getMapper(UserMapper.class);
 
        User user1 = mapper1.findById(1);
        System.out.println(user1.hashCode());
        System.out.println("------------------------------------------");
        User user2 = mapper2.findById(1);
        System.out.println(user2.hashCode());
 
        session.close();
    }
}

执行结果 

        OK,确实返回的哈希值都是一样的,并且我们可以通过控制台输出显示它并没有进行查询而是直接从缓存中拿到对象并返回,所以这就是一级缓存 ,提高了查询效率。

        下面使用不同的SqlSession来进行测试一下,返回的哈希值是否一致 

// 测试使用不同SqlSession查询
    @Test
    public void testCache2() throws Exception{
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        SqlSession session1 = factory.openSession();
        SqlSession session2 = factory.openSession();
 
        // 测试使用不同SqlSession查询
        UserMapper mapper1 = session1.getMapper(UserMapper.class);
        UserMapper mapper2 = session2.getMapper(UserMapper.class);
 
        User user1 = mapper1.findById(1);
        System.out.println(user1.hashCode());
        System.out.println("---------------------------------");
        User user2 = mapper2.findById(1);
        System.out.println(user2.hashCode());
 
        session1.close();
        session2.close();
    }

运行结果

        OK,可以看到,返回的哈希值不一样,并且从控制台输出显示也可以看到这里的确也进行了一次查询,因此可以证实,共享一级缓存确实是基于SqlSession对象的 

(2)清空一级缓存

        但是吧,如果缓存过多的话,也是会影响我们的查询效率的,所以这时候就需要清空缓存了,就像我们时不时要清理一下手机缓存否则就会很卡,是同样的道理,那怎么清空一级缓存呢?

进行以下操作可以清空MyBatis一级缓存:

  • SqlSession 调用 close() :操作后SqlSession对象不可用,该对象的缓存数据也不可用。
  • SqlSession 调用 clearCache() / commit() :操作会清空一级缓存数据。
  • SqlSession 调用增删改方法:操作会清空一级缓存数据,因为增删改后数据库发生改变,缓存数据将不准确
// 清空Mybatis一级缓存
    @Test
    public void testCache3() throws Exception{
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        SqlSession session = factory.openSession();
 
        UserMapper mapper1 = session.getMapper(UserMapper.class);
        UserMapper mapper2 = session.getMapper(UserMapper.class);
 
        User user1 = mapper1.findById(1);
        System.out.println(user1.hashCode());
 
        // 清空Mybatis一级缓存
        session.clearCache();
 
        System.out.println("-------------------------------");
        User user2 = mapper2.findById(1);
        System.out.println(user2.hashCode());
 
        session.close();
    }

执行效果

        OK,返回的哈希值也确实不一样, 但是我们有没有观察到这和上面使用不同的SqlSession对象来执行查询的时候,控制台输入显示有点不一样,那就是这里不用再建立JDBC连接,也有效了提高查询效率,所以我们偶尔还是要清空一下缓存才行

三、Mybatis二级缓存

MyBatis二级缓存也叫全局缓存。数据存放在SqlSessionFactory中,只要是同一个工厂对象创建的SqlSession,在进行查询时都能共享数据。一般在项目中只有一个SqlSessionFactory对象,所以二级缓存的数据是全项目共享的。
MyBatis一级缓存存放的是对象,二级缓存存放的是对象的数据。所以要求二级缓存存放的POJO必须是可序列化的,也就是要实现Serializable接口。
MyBatis二级缓存默认不开启,手动开启后数据先存放在一级缓存中,只有一级缓存数据清空后,数据才会存到二级缓存中。           
SqlSession 调用 clearCache() 无法将数据存到二级缓存中。

(1)开启二级缓存

1. POJO类实现Serializable接口

import java.io.Serializable;
 
public class User implements Serializable {
    private int id;
    private String username;
    private String sex;
    private String address;
}

2. 在Mybatis配置文件添加如下设置

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

这里有个额外知识,就是Mybatis配置文件的标签还得按照顺序来放的,否则就会以下编译错误;

The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,

objectWrapperFactory?,reflectorFactory?,plugins?,environments?,

databaseIdProvider?,mappers?)". 

  同时也说明了放置顺序就得按照match里面的顺序来放

3. 添加 <cache /> 标签

 如果查询到的集合中对象过多,二级缓存只能缓存1024个对象引用。可以通过

<cache /> 标签的size属性修改该数量。

比如:<cache size="2048"/>

(2)测试二级缓存

        那怎么测试呢,从上面我们可以知道二级缓存存放的是对象的数据,并且是基于SqlSessionFactory的,因此我们可以用SqlSessionFactory获取两个SqlSession对象,然后让他们分别获取各自的mapper,然后进行查询,返回到同一个实例化的USer对象中,如果返回的数据是一致的,但是对象的哈希值是不一样的话,则说明二级缓存里存放的确实对象的数据而不是对象。

// 测试二级缓存
@Test
public void testCache4() throws Exception {
    InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(is);
    SqlSession session = factory.openSession();

    UserMapper mapper1 = session.getMapper(UserMapper.class);
    UserMapper mapper2 = session.getMapper(UserMapper.class);

    User user1 = mapper1.findById(1);
    System.out.println(user1);
    System.out.println(user1.hashCode());

    // 让一级缓存失效
    session.commit();
    System.out.println("----------------------------");

    user1 = mapper2.findById(1);
    System.out.println(user1);
    System.out.println(user1.hashCode());
}

运行结果 

        OK,从运行结果上我们可以知道结果集返回到同一个对象中,而他们的哈希值反而不一样,说明执行第二次查询的时候新建了一个对象并且该对象指向那个对象并且将SqlSessionFactory中的数据赋值到新建的那个对象。其实从控制台打印的日志我们也可以得出,并没有执行查询方法,因为没有打印SQL语句,而且缓存也是从0.0改成了0.5,因此我们可以断定二级缓存存放的是数据而不是对象。

到此这篇关于Java Mybatis一级缓存和二级缓存的文章就介绍到这了,更多相关Mybatis一级缓存和二级缓存内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JavaMybatis一级缓存和二级缓存

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JavaMybatis一级缓存和二级缓存

缓存是内存当中一块存储数据的区域,目的是提高查询效率,降低服务器和数据库的压力,这篇文章主要介绍了Mybatis一级缓存和二级缓存,感兴趣的同学可以参考阅读本文
2023-05-14

一文搞懂MyBatis一级缓存和二级缓存

本文主要介绍了一文搞懂MyBatis一级缓存和二级缓存,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-19

mybatis一级缓存和二级缓存是什么

mybatis一级缓存和二级缓存是mybatis提供的两种不同层次的缓存机制,一级缓存是mybatis中默认开启的缓存机制,它是基于线程的本地缓存,二级缓存是基于namespace级别的缓存,可以被多个SqlSession对象共享。本教程操
2023-08-09

Java Mybatis一级缓存和二级缓存是什么

本篇内容主要讲解“Java Mybatis一级缓存和二级缓存是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java Mybatis一级缓存和二级缓存是什么”吧!一、什么是缓存
2023-07-05

Spring中一级缓存、二级缓存和三级缓存有什么作用

今天小编给大家分享一下Spring中一级缓存、二级缓存和三级缓存有什么作用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。缓存
2023-06-29

mybatis一级缓存和二级缓存有什么区别

MyBatis的一级缓存和二级缓存是两种不同级别的缓存机制。一级缓存是在同一个SqlSession内部的缓存,它默认是开启的。在执行查询操作时,查询的结果会被缓存到一级缓存中,下次执行相同的查询操作时,会直接从缓存中获取结果,而不需要再次查
2023-08-20

MyBatis中二级缓存和一级缓存有什么区别

MyBatis中的一级缓存是SqlSession级别的缓存,即在同一个SqlSession中执行相同的查询,第一次查询结果会被缓存下来,后续再执行相同的查询时,直接从缓存中获取结果,提高查询效率。但是一级缓存的生命周期比较短,当SqlSes
MyBatis中二级缓存和一级缓存有什么区别
2024-03-07

MyBatis中一级缓存与二级缓存的区别

今天就跟大家聊聊有关MyBatis中一级缓存与二级缓存的区别,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一级缓存一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sq
2023-05-31

Mybatis中一级缓存、二级缓存的示例分析

这篇文章主要介绍了Mybatis中一级缓存、二级缓存的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Mybatis 为我们提供了一级缓存和二级缓存,可以通过下图来理解
2023-06-02

MyBatis 延迟加载、一级缓存、二级缓存(详解)

使用ORM框架我们更多的是使用其查询功能,那么查询海量数据则又离不开性能,那么这篇中我们就看下mybatis高级应用之延迟加载、一级缓存、二级缓存。使用时需要注意延迟加载必须使用resultMap,resultType不具有延迟加载功能。一
2023-05-31

深入浅析MyBatis中的一级缓存与二级缓存

本篇文章给大家分享的是有关深入浅析MyBatis中的一级缓存与二级缓存,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。MyBatis缓存我们知道,频繁的数据库操作是非常耗费性能的
2023-05-31

使用MyBatis如何实现一级缓存与二级缓存

这期内容当中小编将会给大家带来有关使用MyBatis如何实现一级缓存与二级缓存,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。MyBatis缓存我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB
2023-05-31

MyBatis一级缓存与二级缓存原理与作用分析

mybatis-plus是一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发、提高效率而生,这篇文章带你了解Mybatis的一级和二级缓存
2022-12-27

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录