首页 > 其他分享 >MyBatis 之五:MyBatis 的缓存机制

MyBatis 之五:MyBatis 的缓存机制

时间:2024-03-15 15:03:11浏览次数:21  
标签:缓存 一级 SQL 二级缓存 SqlSession session 之五 MyBatis

(关注+点赞是我继续的最大动力,谢谢支持!) 

缓存

MyBatis 提供了缓存机制来提高应用程序性能,特别是对于那些频繁读取但更新不那么频繁的数据。

MyBatis 提供了一级缓存和二级缓存

一级缓存(本地缓存)

一级缓存默认是开启,可以直接使用的。属于 SqlSession级别的缓存。

  • 一级缓存是 SqlSession 级别的缓存,它在默认情况下是自动开启的。
  • 当同一个 SqlSession 执行 SQL 查询时,如果查询条件相同,MyBatis会首先检查一级缓存中是否存在该查询结果。如果存在,则直接从缓存返回数据,不再执行数据库查询操作。
  • 一级缓存生命周期与 SqlSession 绑定,也就是说,一旦 SqlSession 关闭,一级缓存就会被清空。
  • 对于任何 INSERT、UPDATE 或 DELETE 操作,MyBatis 都会清空当前 SqlSession 中的一级缓存,以确保缓存中的数据与数据库保持同步。
一级缓存验证
/**
 * 一级缓存,SqlSession级别的缓存
 *
 * * 1.sqlSession.clearCache();//清空缓存
 * * 2.flushCache="true"  在映射文件中<select>
 * * 3.执行了更新操作:update insert delele
 * * 4.sqlSession.commit();  rollback(); //引起清空一级缓存的
 * * 5.不同的映射或SQL 都不能相互缓存
 */
public class TestLeveOne {

    public static void main(String[] args) {
        SqlSession session = MyBatisUtil.getSqlSession();
        IDeptDao deptDao = session.getMapper(IDeptDao.class);
        Dept dept1 = deptDao.get(10); //发起SQL
        System.out.println("---------------------------------------");
        //1.清空缓存
//        session.clearCache();

        //2.回滚
//        session.rollback();

        //3. 更新操作:插入 修改 删除
        Dept dept = new Dept();
        dept.setDname("营销部");
        dept.setDeptno(70);

        deptDao.save(dept); //导致清空缓存

        dept1 = deptDao.get(10); //发起SQL

    }


    /**
     * 证明:
     * 1. 一级缓存默认开启的 存在的
     * 2. 一级缓存是 SqlSession级别的缓存(缓存对象在 SqlSession中创建)。
     *
     */
    public static void test1() {
        SqlSession session = MyBatisUtil.getSqlSession();
        IDeptDao deptDao = session.getMapper(IDeptDao.class);

        Dept dept1 = deptDao.get(10); //发起SQL
        System.out.println("*******************上面语句发起SQL,下面语句因缓存中已经存在此对象,所以不再发起SQL**************************");
        Dept dept2 = deptDao.get(10); //未发起SQL
        System.out.println(dept2.hashCode()+"==通过hashcode() 来查看是否为同一个对象=="+dept1.hashCode());
        //关闭session
        MyBatisUtil.close(session);

        //重新打开一个新的 session 并重新获取新的 dao 对象
        session = MyBatisUtil.getSqlSession();
        deptDao = session.getMapper(IDeptDao.class);
        Dept dept3 = deptDao.get(10); //发起SQL
    }
}
一级缓存失效情况
  • sqlSession.clearCache();//清空缓存
  • flushCache="true" 在映射文件标记中
  • 执行了更新操作:update insert delele
  • sqlSession.commit(); rollback(); //引起清空一级缓存的
  • 不同的映射或SQL 都不能相互缓存

二级缓存

  • 二级缓存是跨 SqlSession 的,它的作用范围更广,可以被多个 SqlSession 共享。
  • 开启二级缓存需要在 MyBatis 的 mapper XML 文件或对应的 Mapper 接口上进行配置,并且可以选择使用自定义的缓存实现或者集成第三方缓存如 EhCache。
  • 当一个 SqlSession 关闭后,其加载到二级缓存中的数据可以在新的 SqlSession 中继续使用,前提是这些数据尚未过期或因数据库更新而失效。
  • 二级缓存同样需要处理并发访问和数据一致性问题,MyBatis 提供了一些策略来管理缓存项的同步和清除。
二级缓存验证

二级缓存开启的,三个关键步骤:

  1. 配置文件中:(现在版本,默认就是true)

    <setting name="cacheEnabled" value="true"/>
  2. 映射文件中,需要配置

    <mapper namespace="com.wdzl.dao.IDeptDao">
        <!--启用缓存-->
        <cache />
    </mapper>
  3. 使用二级缓存时,需要对实体类进行序列化,所以要求实体类要实现接口Serializable

public class TestLevelTwo {
    public static void main(String[] args) {
        test1();
        System.out.println("-----------------------");
        test1();
        test1();
    }
    public static void test1() {
        SqlSession session = MyBatisUtil.getSqlSession();
        IDeptDao deptDao = session.getMapper(IDeptDao.class);
        Dept dept1 = deptDao.get(10); //发起SQL
        MyBatisUtil.close(session);
    }
}

可以通过日志查看到二级缓存命中率:

第三方缓存组件

Mybatis 内部有自己的缓存实现,如何切换第三方缓存组件。

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。

Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点

实现步骤:

二级缓存第三方组件:ehcache

配置文件中配置

因为默认true,

当然,如果这里配置为 false ,二级缓存还是会失效的

可以通过下面验证,默认为 true

System.out.println("二级缓存是否被启用: " + sessionFactory.getConfiguration().isCacheEnabled());

注意:不需要被缓存对象实现序列化接口

  • a. 配置依赖,下载jar

    <dependency>
        <groupId>org.mybatis.caches</groupId>
        <artifactId>mybatis-ehcache</artifactId>
        <version>1.2.1</version>
    </dependency>
  • b. 在映射文件中

    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  • c. 注意:被缓存的对象类,是不需要实现序列化接口的

  • d. 也可以选择自定义配置:在classpath目录下新建ehcache.xml文件

查询执行顺序

MyBatis 在查询数据时的缓存查找顺序是:

首先:当 SqlSession 执行数据库查询操作时,实际上是从一级缓存(本地缓存)开始查找。

  • 如果在当前 SqlSession 中之前已经执行过相同的 SQL 查询,并且结果仍然有效,则直接从一级缓存返回数据,不再去查询二级缓存或数据库。

然后:如果一级缓存未命中,接下来的行为取决于是否配置并启用了二级缓存(全局缓存)

  • 若二级缓存已启用且包含匹配的数据,则会从二级缓存中获取数据,并将该数据放入到当前 SqlSession 的一级缓存中,以便后续请求可以快速使用一级缓存。
  • 若二级缓存未命中或者未启用,则 MyBatis 会直接查询数据库以获取数据,并将查询结果放入一级缓存中。

所以,在 MyBatis 中进行查询时,正确的缓存查找顺序是一级缓存 -> 二级缓存 -> 数据库

标签:缓存,一级,SQL,二级缓存,SqlSession,session,之五,MyBatis
From: https://blog.csdn.net/zp8126/article/details/136738993

相关文章

  • 什么是缓存穿透,缓存击穿,缓存雪崩的详细讲解,以及解决方式?
    什么是缓存穿透,缓存击穿,缓存雪崩的详细讲解,以及解决方式?缓存作用:​ redis缓存加载数据库中的数据,数据库一般在磁盘中,访问磁盘的效率比较低,所以使用redis缓存,将数据加载到运存中,请求访问时直接访问缓存,如果缓存中有结果,直接返回结果,缓存中没有结果,请求会被打到数据库上,在数据库......
  • 【已解决】Mybatis-plus中@TableLogic注解失效问题
    逻辑删除逻辑删除是指通过修改数据的状态或添加额外字段来表示数据的删除状态,而不是直接从数据库中物理删除数据记录。通常,会在数据库表中新增一个字段(如deleted),用来标识数据是否被删除。MyBatisPlus中实现逻辑删除在使用MyBatisPlus进行数据库操作时,实现逻辑删除......
  • mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql、insert、update、delete)
    sqlmapconfig.xml配置MyBatis的配置文件包含了会深深影响MyBatis行为的设置(settings)和属性(properties)信息。文档的顶层结构如下:configuration配置properties属性settings设置typeAliases类型别名typeHandlers类型处理器objectFactory对象工厂plugins插件environ......
  • MybatisPlus
    入门MyBatis-Plus(opensnewwindow)(简称MP)是一个MyBatis(opensnewwindow)的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。准备数据DROPTABLEIFEXISTS`user`;CREATETABLE`user`(idBIGINTNOTNULLCOMMENT'主键ID',name......
  • Mybatis
    概述表现层(UI):直接跟前端打交互(一是接收前端ajax请求,二是返回json数据给前端)业务逻辑层(BLL):一是处理表现层转发过来的前端请求(也就是具体业务),二是将从持久层获取的数据返回到表现层。数据访问层(DAL):直接操作数据库完成CRUD,并将获得的数据返回到上一层(也就是业务逻辑层)。Java持久......
  • 缓存穿透、缓存击穿、缓存雪崩区别
    高并发下缓存雪崩Redis中的数据大面积失效(时间过期)的情景缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。解决方案:均匀过期:给热点数据设置不同的过期时间,给每个key的失效时间加一个随机值;原有的失效时间基......
  • 内存缓存和分布式缓存
    参考官方文档:https://learn.microsoft.com/zh-cn/aspnet/core/performance/caching/overview?view=aspnetcore-6.0内存中缓存可以存储任何对象。分布式缓存接口仅限于byte[],应用程序需要自行解决针对缓存对象的序列化和反序列化问题。内存中和分布式缓存都将缓存项存储为键值......
  • 开启mybatis二级缓存
    mybatis的二级缓存是mapper级别的,也就是同一个mapper下的查询,可以使用缓存里面的值下面就写个demo记录下没有使用缓存之前service@OverridepublicDevicegetUserById(Longid){DevicebyId=deviceMapper.getDeviceById(id);log.info("=======......
  • mybatis中常见的动态SQL标签
    在xml中写动态SQL的的时候,有一些常见的,如if、foreachSELECTa.*,c.product_nameFROMwork_orderaLEFTJOINproductcONa.product_code=c.product_codeANDc.del_flag=0wherea.del_flag=0<iftest="orderQueryReq.productCode......
  • mybatis plus saveBatch报错问题
    sessionRecordHumanService.saveBatch(dataList);具体报错如下:org.mybatis.spring.MyBatisSystemException:nestedexceptionisorg.apache.ibatis.exceptions.PersistenceException: ###Errorupdatingdatabase.Cause:java.lang.IllegalArgumentException:MappedSta......