mybatis中的缓存问题解析

发布时间 - 2026-01-11 00:40:01    点击率:

关于mybatis基础我们前面几篇博客已经介绍了很多了,今天我们来说一个简单的问题,那就是mybatis中的缓存问题。mybatis本身对缓存提供了支持,但是如果我们没有进行任何配置,那么默认情况下系统只开启了一级缓存,一级缓存就是同一个SqlSession执行的相同查询是会进行缓存的,OK,那么今天我们就来看看这些缓存,并简单验证下。

系统默认开启了一级缓存

这个缓存系统默认情况下是开启的,当我们获取到一个SqlSession对象之后,如果调用SqlSession中的同一个方法查询同一条数据,那么第二次查询将不会去数据库中查询,因为第一次查询有缓存,直接调用缓存数据即可,除非缓存超时或者我们明确声明数据要刷新,否则都是直接调用缓存数据。OK,我们来看一个简单的案例。
查询代码如下:

SqlSession sqlSession = null;
    try {
      sqlSession = DBUtils.openSqlSession();
      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      //查询同一条数据时会缓存
      User user = mapper.getUser(1l);
      User user2 = mapper.getUser(1l);
      System.out.println(user.toString());
      System.out.println(user2.toString());
      sqlSession.commit();
    } catch (Exception e) {
      System.err.println(e.getMessage());
      sqlSession.rollback();
    } finally {
      if (sqlSession != null) {
        sqlSession.close();
      }
    }

我们来看看日志:

 

小伙伴们看到,我这里执行了两次查询,但实际上只执行了一次SQL语句。

自己配置二级缓存

上面的缓存是由系统默认配置的,这个有一定的局限性,就是只能在同一个SqlSession中有效,脱离了同一个SqlSession就没法使用这个缓存了,有的时候我们可能希望能够跨SqlSession进行数据缓存。那么这个时候需要我们进行手动开启二级缓存。

二级缓存的开启方式其实很简单,只需要我们在userMapper.xml中配置<cache/>节点即可。如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.UserMapper">
  <cache/>
  <select id="getUser" resultType="org.sang.bean.User" parameterType="Long">
    select * from user where id = #{id}
  </select>
  <insert id="insertUser" parameterType="org.sang.bean.User">
    INSERT INTO user(username,password,address) VALUES (#{username},#{password},#{address})
  </insert>
  <delete id="deleteUser" parameterType="Long">
    DELETE FROM user where id=#{id}
  </delete>
  <select id="getAll" resultType="u">
    SELECT * from user
  </select>
</mapper>

这样简单配置之后,二级缓存就算开启了,这样的配置中,许多东西都是默认的,比如所有的select语句都会被缓存,所有的delete、insert和update则都会将缓存刷新,还比如缓存将使用LRU算法进行内存回收等。那么这些东西如果需要配置的话,我们可以按如下方式进行配置:

<cache eviction="LRU" flushInterval="20000" size="1024" readOnly="true"/>,这里的eviction表示缓存策略,除了LRU之外还有先进先出(FIFO)、软引用(SOFT)、弱引用(WEAK)等,flushInterval则表示刷新时间,表示缓存的对象个数,readOnly为true则表示缓存只可以读取不可以修改。

OK,做了如上配置之后还不够,开启二级缓存还要求我们的实体类可以序列化,实现Serializable接口即可,如下:

public class User implements Serializable{
  private Long id;
  private String username;
  private String password;
  private String address;

  ...

}

如此之后,我们的二级缓存就算成功开启了,OK,我么来测试下:

SqlSession sqlSession = null;
    SqlSession sqlSession2 = null;
    try {
      sqlSession = DBUtils.openSqlSession();
      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      User user = mapper.getUser(1l);
      System.out.println(user.toString());
      sqlSession.commit();
      sqlSession2 = DBUtils.openSqlSession();
      UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
      User user2 = mapper2.getUser(1l);
      System.out.println(user2.toString());
      sqlSession2.commit();
    } catch (Exception e) {
      System.err.println(e.getMessage());
      sqlSession.rollback();
      sqlSession2.rollback();
    } finally {
      if (sqlSession != null) {
        sqlSession.close();
      }
      if (sqlSession2 != null) {
        sqlSession2.close();
      }
    }

打印日志如下:

 

OK,小伙伴们看到SQL语句实际上只执行了一次。

OK,以上就是对mybatis中缓存的一个简单介绍。

本文案例下载: 本文案例GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test27-mybatis8

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# mybatis  # 缓存  # 缓存问题  # mybatis缓存配置  # 【MyBatis源码全面解析】MyBatis一二级缓存介绍  # 深入理解MyBatis中的一级缓存与二级缓存  # mybatis二级缓存默认未开启源码的问题  # 都是  # 开启了  # 上只  # 情况下  # 直接调用  # 小伙伴们  # 是由  # 不可以  # 两次  # 有一定  # 我们可以  # 来看看  # 这个时候  # 只需要  # 当我们  # 就来  # 会去  # 还不够  # 将不  # 会将 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】  php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】  免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  常州企业网站制作公司,全国继续教育网怎么登录?  微信小程序 input输入框控件详解及实例(多种示例)  如何登录建站主机?访问步骤全解析  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  Android自定义控件实现温度旋转按钮效果  html5怎么画眼睛_HT5用Canvas或SVG画眼球瞳孔加JS控制动态【绘制】  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  如何确保FTP站点访问权限与数据传输安全?  标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南  Laravel如何处理CORS跨域请求?(配置示例)  浅谈redis在项目中的应用  JavaScript如何实现错误处理_try...catch如何捕获异常?  如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程  原生JS实现图片轮播切换效果  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】  如何在阿里云购买域名并搭建网站?  如何在万网ECS上快速搭建专属网站?  如何在万网利用已有域名快速建站?  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  JS弹性运动实现方法分析  高防网站服务器:DDoS防御与BGP线路的AI智能防护方案  如何批量查询域名的建站时间记录?  移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?  惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?  如何快速生成可下载的建站源码工具?  php在windows下怎么调试_phpwindows环境调试操作说明【操作】  Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID  Android仿QQ列表左滑删除操作  Laravel怎么发送邮件_Laravel Mail类SMTP配置教程  如何在 Pandas 中基于一列条件计算另一列的分组均值  JavaScript常见的五种数组去重的方式  昵图网官方站入口 昵图网素材图库官网入口  javascript日期怎么处理_如何格式化输出  Laravel如何自定义分页视图?(Pagination示例)  Laravel如何使用Livewire构建动态组件?(入门代码)  如何在Windows环境下新建FTP站点并设置权限?  Laravel如何与Inertia.js和Vue/React构建现代单页应用  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案  黑客如何利用漏洞与弱口令入侵网站服务器?  音乐网站服务器如何优化API响应速度?  1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤