Mybatis缓存

简介: Mybatis缓存

简介


什么是缓存


缓存在我们工作生活中经常被提及,比如“怎么清理浏览器的缓存”,“手机内存不够了,如何删除缓存”,“硬盘的缓存是不是越大越好”等等。


其实这些“缓存”可以分为三类:

  • 硬件缓存:指的是一块芯片,可以被集成到硬盘或 CPU 上。它用来充当硬盘(CPU)与外界接口(通常是内存)之间的暂存器。利用缓存可以减轻系统的负荷,同时提高数据的传输速率。
  • 客户端缓存:某些应用,比如浏览器、微信,为了实现快速响应用户的请求,会把用户之前浏览的东西(文字或图片等)存在本地。在下次访问时,如果本地的缓存里有请求的内容,那么就直接展示出来,不用再次向服务器发送请求,等待服务器响应。
  • 服务端缓存:它与客户端缓存目的相同,只不过是站在服务器的角度考虑。如果每次接到客户端请求都要连接一次数据库,当用户请求过多,将会导致负载过大。这时可以把一些经常被请求的数据存放在内存中,当有请求时直接返回,不用连接数据库,这样可以减轻数据库的负担。


关于缓存的定义,总结为一句话就是:缓存是临时存放数据(使用频繁的数据)的地方,介于外部请求和真实数据之间。


为什么要用缓存


  1. 缓解服务器压力(不用每次去请求资源);
  2. 提升性能(打开本地资源速度当然比请求回来再打开要快得多);
  3. 减少带宽消耗;


缓存中的一些术语


命中(HIT):当客户端发起一个请求,如果被请求的资源在缓存中,这个资源就会被使用,我们就叫它缓存命中。


未命中(MISS):当客户端发起一个请求,如果没有在缓存追踪找到,我们称这种 情况为缓存未命中。这时需要查询数据库,并且将查询结果加入缓存中。


存储成本:当未命中时,我们会从数据库中取出数据,然后加入到缓存中。把这个数据放入缓存所需要的时间和空间,就是 存储成本。


失效:当缓存中的数据需要更新时,就意味着当前缓存中的这个数据失效了。缓存中的数据需要同步进行更新操作。还有一种情况就是该缓存过了失效时间。因为缓存会占用内存,缓存量过大会引发别的问题,我们一般都会设置失效时间来让缓存定时过期失效。


失效策略:如果缓存满了,而当前请求又没有命中缓存,那么就会按照某一种策略,把缓存中的某个旧资源剔除,而把新的资源加入缓存。这些决定应该剔除哪个旧资源的策略统称为失效策略(缓存算法)。


常见的一般策略有:

  • FIFO(first in first out) :先进先出策略,最先进入缓存的数据在缓存空间不够的情况下(超出最大元素限制)会被优先被清除掉,以腾出新的空间接受新的数据。策略算法主要比较缓存元素的创建时间。在数据实效性要求场景下可选择该类策略,优先保障最新数据可用。
  • LFU(less frequently used) :最少使用策略。无论是否过期,根据元素的被使用次数判断,清除使用次数较少的元素释放空间。策略算法主要比较元素的 hitCount(命中次数)。在保证高频数据有效性场景下,可选择这类策略。
  • LRU(least recently used) :最近最少使用策略。无论是否过期,根据元素最后一次被使用的时间戳,清除最远使用时间戳的元素释放空间。策略算法主要比较元素最近一次被get使用时间。在热点数据场景下较适用,优先保证热点数据的有效性。  


除此之外,还有一些简单策略比如:

  • 根据过期时间判断,清理过期时间最长的元素;
  • 根据过期时间判断,清理最近要过期的元素;
  • 随机清理;
  • 根据关键字(或元素内容)长短清理等。


Mybatis缓存


Mybatis 缓存属于服务端缓存。

MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。

MyBatis 系统中默认定义了两级缓存:一级缓存二级缓存

  • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
  • 二级缓存需要手动开启和配置,它是基于 namespace 级别的缓存,缓存只作用于 cache 标签所在的映射文件中的语句。


一级缓存


一级缓存也叫本地缓存,它仅仅对一个会话中的数据进行缓存,在 Mybatis 中是指 SqlSession 对象开启到关闭的这段时间里称为一个会话。

在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的SQL,MyBatis 提供了一级缓存的方案优化这部分场景,如果是相同的 SQL 语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。具体执行过程如下图所示。



每个 SqlSession 中持有了 Executor,每个 Executor 中有一个 LocalCache。当用户发起查询时,MyBatis 根据当前执行的语句生成 MappedStatement,在 Local Cache 进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入Local Cache,最后返回结果给用户。


实例分析


1、在测试项目中加入日志记录,方便查看效果。


2、User 实体类


@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private int id;
    private String name;
    private String password;
}
复制代码


3、编写接口


User getUser(@Param("id") int id);
复制代码


4、接口配置文件


<resultMap id="userMap" type="User">
    <result property="password" column="pwd" />
</resultMap>
<select id="getUser" resultMap="userMap">
    select * from mybatis.user where id=#{id}
</select>
复制代码


5、mybatis-config.xml


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置文件-->
<configuration>
    <properties resource="db.properties" />
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <typeAliases>
        <package name="com.msdn.bean"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <!--jdbc.url=jdbc:mysql://localhost:3306/oto?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC-->
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/msdn/mapper/UserMapper.xml"/>
    </mappers>
</configuration>
复制代码


6、测试


@Test
    public void getUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUser(1);
        System.out.println(user);
        User user2 = userMapper.getUser(1);
        System.out.println(user);
        System.out.println(user == user2);
        sqlSession.close();
    }
复制代码


7、结果分析


2020-03-21 20:39:58,472 DEBUG [com.msdn.mapper.UserMapper] - Cache Hit Ratio [com.msdn.mapper.UserMapper]: 0.0
2020-03-21 20:39:58,704 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 20:39:58,731 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 20:39:58,747 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
2020-03-21 20:39:58,748 DEBUG [com.msdn.mapper.UserMapper] - Cache Hit Ratio [com.msdn.mapper.UserMapper]: 0.0
User(id=1, name=hresh, password=123456)
true
复制代码


通过日志记录可以看出,SQL 语句只执行了一次,第二次获取 User 对象并未查询数据库,最后两个对象比较结果为 true 也说明是同一个对象。


一级缓存失效


一级缓存是默认开启且无法关闭的, 基于  SqlSession 级别。我们说的一级缓存失效,指的是在 SqlSession 对象存活期间,不止一次向数据库发送数据请求。


1、SqlSession 对象不同


@Test
    public void getUser2(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        SqlSession sqlSession2 = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUser(1);
        System.out.println(user);
        sqlSession.close();
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = userMapper2.getUser(1);
        System.out.println(user);
        System.out.println(user == user2);
        sqlSession2.close();
    }
复制代码


执行结果为:


2020-03-21 21:45:48,085 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 21:45:48,118 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 21:45:48,138 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
2020-03-21 21:45:48,139 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 21:45:48,140 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 21:45:48,141 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
false
复制代码


从结果中可以看出执行过程中有两条 SQL 语句,可以得出结论 :每个 sqlSession 中的缓存是独立的。


2、SqlSession 对象相同,查询请求不同


@Test
    public void getUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUser(1);
        System.out.println(user);
        User user2 = userMapper.getUser(2);
        System.out.println(user2);
        System.out.println(user == user2);
        sqlSession.close();
    }
复制代码


执行结果为:


2020-03-21 21:52:34,817 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 21:52:34,854 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 21:52:34,871 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
2020-03-21 21:52:34,872 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 21:52:34,872 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 2(Integer)
2020-03-21 21:52:34,874 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=2, name=hresh2, password=123456)
false
复制代码


同样发现有两条 SQL 语句,说明同一 SqlSession 下的缓存中添加新的数据需要请求数据库。


3、SqlSession 相同,两次查询操作之间执行了增删改操作


@Test
    public void getUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUser(1);
        System.out.println(user);
        //增删改操作,可能会修改原来的数据,所以必定会刷新缓存
        User user1 = new User(4,"acorn22","12344");
        userMapper.updateUser(user1);
        User user2 = userMapper.getUser(1);
        System.out.println(user2);
        System.out.println(user == user2);
        sqlSession.close();
    }
复制代码


执行结果:


2020-03-21 21:58:51,685 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 21:58:51,721 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 21:58:51,738 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
2020-03-21 21:58:51,740 DEBUG [com.msdn.mapper.UserMapper.updateUser] - ==>  Preparing: update mybatis.user set name=? where id=? 
2020-03-21 21:58:51,741 DEBUG [com.msdn.mapper.UserMapper.updateUser] - ==> Parameters: acorn22(String), 4(Integer)
2020-03-21 21:58:51,748 DEBUG [com.msdn.mapper.UserMapper.updateUser] - <==    Updates: 1
2020-03-21 21:58:51,749 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 21:58:51,749 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 21:58:51,751 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
false
复制代码


两次查询操作之间执行了修改操作,修改操作后再做任何操作,都会重新请求数据库。说明增删改操作可能会对数据库中的数据产生影响。


4、SqlSession 相同,手动清除一级缓存


@Test
    public void getUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUser(1);
        System.out.println(user);
        //手动清理缓存
        sqlSession.clearCache();
        User user2 = userMapper.getUser(1);
        System.out.println(user2);
        System.out.println(user == user2);
        sqlSession.close();
    }
复制代码


执行结果:


2020-03-21 22:03:34,909 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 22:03:34,947 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 22:03:34,965 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
2020-03-21 22:03:34,965 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 22:03:34,966 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 22:03:34,967 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
false
复制代码


可以认为一级缓存是个 map 集合,做了 clear 操作。


二级缓存


在上文中提到的一级缓存中,其最大的共享范围就是一个 SqlSession 内部,如果多个 SqlSession 之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在CachingExecutor 进行二级缓存的查询,具体的工作流程如下所示。



二级缓存开启后,同一个 namespace 下的所有操作语句,都影响着同一个 Cache,即二级缓存被多个 SqlSession 共享,是一个全局的变量。

当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。


实例分析


1、在 mybatis-config.xml 中开启全局缓存


<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
复制代码


2、在对应的 Mapper 配置文件中配置二级缓存


<cache
       eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>
复制代码


3、测试

首先需要将 JavaBean 类实现序列化接口。


/**
     * 首先需要开启二级缓存,只在同一个Mapper下有效;
     * 所有的数据都会先放在一级缓存中;
     * 只有当会话提交,或关闭时,才会提交到二级缓存中。
     *
     * */
    @Test
    public void getUser2(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        SqlSession sqlSession2 = MybatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUser(1);
        System.out.println(user);
        sqlSession.close();
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = userMapper2.getUser(1);
        System.out.println(user);
        System.out.println(user == user2);
        sqlSession2.close();
    }
复制代码


执行结果:


2020-03-21 22:22:04,323 DEBUG [com.msdn.mapper.UserMapper] - Cache Hit Ratio [com.msdn.mapper.UserMapper]: 0.0
2020-03-21 22:22:04,668 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==>  Preparing: select * from mybatis.user where id=? 
2020-03-21 22:22:04,707 DEBUG [com.msdn.mapper.UserMapper.getUser] - ==> Parameters: 1(Integer)
2020-03-21 22:22:04,729 DEBUG [com.msdn.mapper.UserMapper.getUser] - <==      Total: 1
User(id=1, name=hresh, password=123456)
2020-03-21 22:22:04,731 DEBUG [com.msdn.mapper.UserMapper] - Cache Hit Ratio [com.msdn.mapper.UserMapper]: 0.5
User(id=1, name=hresh, password=123456)
true
复制代码


结论:


只要开启了二级缓存,在同一个 Mapper 中做的查询,数据都会存放在二级缓存中。数据首先会放在一级缓存中,当 sqlSession 对象提交或关闭后,一级缓存中的数据才会转到二级缓存中。


缓存原理



EhCache


ehcache 是一个用 Java 实现的使用简单,高速,实现线程安全的缓存管理类库,ehcache 提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的 cache 管理方案。


使用步骤


1、导入相关依赖


<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.1.0</version>
</dependency>
复制代码


2、修改 Mapper 配置文件


<mapper namespace = “org.acme.FooMapper” > 
    <cache type = “org.mybatis.caches.ehcache.EhcacheCache” /> 
</mapper>
复制代码


3、编写 ehcache.xml 文件,如果在加载时未找到/ehcache.xml资源或出现问题,则将使用默认配置。


<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!--
       diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
       user.home – 用户主目录
       user.dir  – 用户当前工作目录
       java.io.tmpdir – 默认临时文件路径
     -->
    <diskStore path="java.io.tmpdir/Tmp_EhCache"/>
    <!--
       defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
     -->
    <!--
      name:缓存名称。
      maxElementsInMemory:缓存最大数目
      maxElementsOnDisk:硬盘最大缓存个数。
      eternal:对象是否永久有效,一但设置了,timeout将不起作用。
      overflowToDisk:是否保存到磁盘,当系统当机时
      timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
      timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
      diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
      diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
      memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
      clearOnFlush:内存数量最大时是否清除。
      memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
      FIFO,first in first out,这个是大家最熟的,先进先出。
      LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
      LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
   -->
    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>
    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
</ehcache>


目录
相关文章
|
3月前
|
缓存 Java 数据库连接
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
文章介绍了MyBatis的缓存机制,包括一级缓存和二级缓存的配置和使用,以及如何整合第三方缓存EHCache。详细解释了一级缓存的生命周期、二级缓存的开启条件和配置属性,以及如何通过ehcache.xml配置文件和logback.xml日志配置文件来实现EHCache的整合。
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
|
23天前
|
缓存 Java 数据库连接
MyBatis缓存机制
MyBatis提供两级缓存机制:一级缓存(Local Cache)默认开启,作用范围为SqlSession,重复查询时直接从缓存读取;二级缓存(Second Level Cache)需手动开启,作用于Mapper级别,支持跨SqlSession共享数据,减少数据库访问,提升性能。
29 1
|
27天前
|
缓存 Java 数据库连接
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
44 4
|
1月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
SQL 缓存 Java
MyBatis如何关闭一级缓存(分注解和xml两种方式)
MyBatis如何关闭一级缓存(分注解和xml两种方式)
83 5
|
6月前
|
SQL 缓存 Java
MYBATIS缓存
MYBATIS缓存
|
2月前
|
缓存 Java 数据库连接
使用MyBatis缓存的简单案例
MyBatis 是一种流行的持久层框架,支持自定义 SQL 执行、映射及复杂查询。本文介绍了如何在 Spring Boot 项目中集成 MyBatis 并实现一级和二级缓存,以提高查询性能,减少数据库访问。通过具体的电商系统案例,详细讲解了项目搭建、缓存配置、实体类创建、Mapper 编写、Service 层实现及缓存测试等步骤。
|
5月前
|
SQL 缓存 Java
【面试官】Mybatis缓存有什么问题吗?
面试官:你说下对MyBatis的理解?面试官:那SqlSession知道吧?面试官:Mybatis的缓存有哪几种?面试官:那Mybatis缓存有什么问题吗?面试官:Mybatis分页插件是怎么
【面试官】Mybatis缓存有什么问题吗?
|
5月前
|
缓存 算法 Java
关于MyBatis的缓存详解
MyBatis 的缓存机制非常灵活,可以通过简单的配置来满足不同的性能需求。合理地使用缓存可以显著提高应用程序的性能,尤其是在处理大量数据库查询时。然而,开发者需要注意缓存的一致性和并发问题,特别是在使用可读写缓存时。
|
6月前
|
缓存 NoSQL Java
在 SSM 架构(Spring + SpringMVC + MyBatis)中,可以通过 Spring 的注解式缓存来实现 Redis 缓存功能
【6月更文挑战第18天】在SSM(Spring+SpringMVC+MyBatis)中集成Redis缓存,涉及以下步骤:添加Spring Boot的`spring-boot-starter-data-redis`依赖;配置Redis连接池(如JedisPoolConfig)和连接工厂;在Service层使用`@Cacheable`注解标记缓存方法,指定缓存名和键生成策略;最后,在主配置类启用缓存注解。通过这些步骤,可以利用Spring的注解实现Redis缓存。
85 2