Spring Boot 整合 MyBatis 中使用一级缓存与二级缓存详解(含完整示例)

0 阅读4分钟

💡 一、前言

在实际开发中,数据库查询往往是最容易成为性能瓶颈的地方。为了提升系统响应速度和减轻数据库压力,缓存机制 成为不可或缺的一部分。

MyBatis 提供了两种级别的缓存支持:

  • 一级缓存(本地缓存)
  • 二级缓存(全局缓存)

本文将带你深入理解 MyBatis 的一级缓存和二级缓存,并结合 Spring Boot 给出完整的整合示例,帮助你在项目中高效地使用缓存技术。


🛠️ 二、环境准备

1. 添加依赖(pom.xml

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- MyBatis Starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.2</version>
    </dependency>

    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Ehcache(用于二级缓存) -->
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-core</artifactId>
        <version>2.6.11</version>
    </dependency>
</dependencies>

2. 数据库配置(application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.demo.model

🧪 三、MyBatis 一级缓存(Session 级别)

✅ 什么是 MyBatis 一级缓存?

MyBatis 的 一级缓存是基于 SqlSession 的本地缓存,默认开启。它只对当前会话有效,当会话关闭或提交后缓存失效。

✅ 使用场景

适合在一个请求内重复查询相同数据的场景,例如:

  • 同一个用户信息被多次调用;
  • 查询结果不变的数据在一次事务中多次使用;

✅ 示例代码

@Mapper
public interface UserMapper {
    User selectById(Integer id);
}
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public void testFirstLevelCache() {
        User user1 = userMapper.selectById(1);
        User user2 = userMapper.selectById(1); // 第二次查询走一级缓存

        System.out.println(user1 == user2); // true
    }
}

✅ 缓存失效条件

  • SqlSession 关闭;
  • 执行增删改操作;
  • 手动清空缓存(sqlSession.clearCache());

🧢 四、MyBatis 二级缓存(Mapper 级别)

✅ 什么是 MyBatis 二级缓存?

MyBatis 的 二级缓存是跨 SqlSession 的共享缓存,作用范围是 namespace,即每个 Mapper 接口拥有独立的缓存空间。

默认情况下,MyBatis 不开启二级缓存,需要手动配置。

✅ 开启步骤

1. 实体类实现 Serializable 接口(必须)

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
    private Integer id;
    private String name;
}

2. 在 Mapper XML 文件中添加 <cache> 标签

<mapper namespace="com.example.demo.mapper.UserMapper">
    <cache/> <!-- 开启二级缓存 -->

    <select id="selectById" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>
</mapper>

3. 全局配置启用二级缓存(可选)

mybatis:
  configuration:
    cache-enabled: true

✅ 示例代码

@Test
public void testSecondLevelCache() {
    SqlSession session1 = sqlSessionFactory.openSession();
    UserMapper mapper1 = session1.getMapper(UserMapper.class);
    User user1 = mapper1.selectById(1);
    session1.close(); // 关闭第一个会话

    SqlSession session2 = sqlSessionFactory.openSession();
    UserMapper mapper2 = session2.getMapper(UserMapper.class);
    User user2 = mapper2.selectById(1); // 第二次查询走二级缓存
    session2.close();

    System.out.println(user1 == user2); // false(对象不同,但数据一致)
}

✅ 缓存失效条件

  • 增删改操作(自动清除缓存);
  • 手动刷新缓存;
  • 设置过期时间(需引入第三方缓存如 Ehcache);

🧠 五、MyBatis 二级缓存优化 —— 使用 Ehcache

虽然 MyBatis 自带的二级缓存可以使用,但功能有限,推荐使用 EhcacheRedis 来增强缓存能力。

1. 引入 Ehcache 配置文件(ehcache.xml

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="1000"
        eternal="false"
        timeToIdleSeconds="600"
        timeToLiveSeconds="1200"
        overflowToDisk="true"
    />
</ehcache>

2. 修改 Mapper XML 文件,指定缓存实现类

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

3. 实体类仍需实现 Serializable

public class User implements Serializable { ... }

🧭 六、进阶技巧与最佳实践

技巧描述适用场景
缓存穿透缓存和数据库都没有的数据攻击使用布隆过滤器
缓存击穿某个热点数据缓存失效导致大量请求打到 DB设置永不过期 + 异步更新
缓存雪崩大量缓存同时失效设置随机过期时间
缓存预热提前加载常用数据到缓存中系统启动时初始化

🔍 七、常见问题与解决方案

问题描述解决方案
二级缓存不生效未实现 Serializable 接口补充接口实现
两次查询返回不同对象二级缓存默认不会复用对象引用无需关注,数据一致即可
更新后缓存未失效未执行写操作触发清缓存确保执行 insert / update / delete 操作
缓存配置无效未正确配置 Ehcache 路径检查 ehcache.xml 路径及依赖版本

📘 八、总结对比表

特性一级缓存二级缓存
作用域单个 SqlSession 内Mapper 级别(多个 Session 共享)
默认状态开启关闭(需手动配置)
存储类型HashMap可自定义(如 Ehcache、Redis)
生命周期与 SqlSession 一致与 Mapper 一致
是否序列化不需要必须实现 Serializable
是否跨会话

📝 九、结语

掌握 MyBatis 的一级缓存和二级缓存机制,不仅能显著提升系统性能,还能减少数据库访问压力,是构建高并发、高性能 Java 应用的重要技能之一。

无论是做后台管理系统、电商系统还是内容平台,合理使用缓存都是必备技能!

如果你觉得有用,欢迎点赞、收藏、转发给更多需要的朋友!