java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > mybatisplus 二级缓存

mybatisplus 配置二级缓存及实战示例

作者:一叶飘零_sweeeet

这篇文章主要介绍了mybatisplus 配置二级缓存及实战示例,包含基础配置、高级特征及实战示例,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧

MyBatis-Plus(简称 MP)作为 MyBatis 的增强工具,完全兼容 MyBatis 的二级缓存机制,同时提供了更便捷的配置方式。以下是基于 MyBatis-Plus 的二级缓存配置全指南,包含基础配置、高级特性及实战示例:

一、二级缓存核心依赖

确保项目中包含 MyBatis-Plus 及缓存相关依赖(以 Spring Boot 为例):

<!-- MyBatis-Plus核心依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>
<!-- 可选:Redis缓存(分布式环境必备) -->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-redis</artifactId>
    <version>1.0.0-beta2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

二、基础配置(本地缓存)

适用于单机环境,使用 MyBatis 默认的内存缓存(PerpetualCache)。

2.1 全局开启二级缓存

application.yml中开启全局缓存开关(MyBatis 默认开启,建议显式配置):

mybatis-plus:
  configuration:
    cache-enabled: true  # 全局启用二级缓存(默认为true)
  mapper-locations: classpath*:mapper/**/*.xml  # 指定Mapper.xml路径

2.2 实体类实现序列化

二级缓存存储对象需支持序列化(避免缓存失败):

package com.example.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class User implements Serializable {
    private static final long serialVersionUID = 1L;  // 必须添加序列化版本号
    @TableId(type = IdType.AUTO)
    private Long id;
    private String username;
    private String email;
    private LocalDateTime createTime;
}

2.3 在 Mapper 中开启二级缓存

有两种方式配置 Mapper 级别的二级缓存,根据项目风格选择:

方式 1:XML 配置(推荐,支持更多缓存参数)

在对应的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="com.example.mapper.UserMapper">
    <!-- 配置二级缓存 -->
    <cache 
        eviction="LRU"        <!-- 缓存淘汰策略:LRU(最近最少使用) -->
        flushInterval="60000" <!-- 自动刷新间隔(60秒) -->
        size="1024"           <!-- 最大缓存对象数 -->
        readOnly="false"/>    <!-- 非只读(需序列化) -->
    <!-- MP自动生成的SQL会自动使用缓存,自定义SQL需显式配置 -->
    <select id="selectById" resultType="com.example.entity.User">
        SELECT id, username, email, create_time AS createTime 
        FROM t_user WHERE id = #{id}
    </select>
</mapper>

方式 2:注解配置(简化配置,适合无 XML 场景)

在 Mapper 接口上使用@CacheNamespace注解:

package com.example.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.CacheNamespace;
import org.apache.ibatis.cache.impl.PerpetualCache;
// 注解方式开启二级缓存,默认使用PerpetualCache
@CacheNamespace(
    eviction = LruCache.class,  // 淘汰策略:LRU
    flushInterval = 60000,      // 刷新间隔60秒
    size = 1024,                // 最大缓存数
    readWrite = true            // 读写模式(非只读)
)
public interface UserMapper extends BaseMapper<User> {
    // 继承BaseMapper的方法会自动使用缓存
}

三、高级配置(分布式缓存,Redis 为例)

单机缓存无法满足分布式环境需求,需集成 Redis 实现缓存共享。

3.1 配置 Redis 连接

创建redis.properties(src/main/resources/):

redis.host=localhost
redis.port=6379
redis.timeout=2000
redis.password=  # 无密码则留空
redis.database=0
redis.default.expiration=1800000  # 缓存默认过期时间(30分钟)

3.2 配置 Mapper 使用 Redis 缓存

方式 1:XML 配置指定 Redis 缓存类型

<mapper namespace="com.example.mapper.UserMapper">
    <!-- 使用Redis作为二级缓存 -->
    <cache type="org.mybatis.caches.redis.RedisCache">
        <property name="eviction" value="LRU"/>
        <property name="flushInterval" value="60000"/>
        <property name="size" value="1024"/>
    </cache>
</mapper>

方式 2:注解配置自定义 Redis 缓存

package com.example.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.CacheNamespace;
import org.mybatis.caches.redis.RedisCache;
// 注解方式指定Redis缓存
@CacheNamespace(implementation = RedisCache.class)
public interface UserMapper extends BaseMapper<User> {
}

3.3 自定义 Redis 缓存(可选,优化序列化)

默认 Redis 缓存使用 Java 序列化,性能较差,可自定义 JSON 序列化:

package com.example.cache;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.mybatis.caches.redis.RedisCache;
import java.util.concurrent.locks.ReadWriteLock;
public class JsonRedisCache extends RedisCache {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    public JsonRedisCache(String id) {
        super(id);
    }
    @Override
    public void putObject(Object key, Object value) {
        try {
            // 序列化为JSON字符串
            String jsonValue = OBJECT_MAPPER.writeValueAsString(value);
            super.putObject(key, jsonValue);
        } catch (Exception e) {
            throw new RuntimeException("缓存序列化失败", e);
        }
    }
    @Override
    public Object getObject(Object key) {
        try {
            String jsonValue = (String) super.getObject(key);
            if (jsonValue != null) {
                // 反序列化为目标对象(根据实际类型调整)
                return OBJECT_MAPPER.readValue(jsonValue, User.class);
            }
        } catch (Exception e) {
            throw new RuntimeException("缓存反序列化失败", e);
        }
        return null;
    }
    // 禁用默认锁(Redis本身是单线程,无需额外锁)
    @Override
    public ReadWriteLock getReadWriteLock() {
        return null;
    }
}

使用自定义缓存:

<cache type="com.example.cache.JsonRedisCache"/>

四、缓存细粒度控制

MyBatis-Plus 支持对单个方法配置缓存策略,覆盖全局设置。

4.1 禁用特定查询的缓存

<!-- XML方式:当前查询不使用二级缓存 -->
<select id="selectByUsername" resultType="User" useCache="false">
    SELECT * FROM t_user WHERE username = #{username}
</select>
// 注解方式:使用@Options禁用缓存
import org.apache.ibatis.annotations.Options;
public interface UserMapper extends BaseMapper<User> {
    @Options(useCache = false)
    User selectByUsername(String username);
}

4.2 强制刷新缓存

<!-- 执行该查询前清空缓存 -->
<select id="selectLatestUsers" resultType="User" flushCache="true">
    SELECT * FROM t_user ORDER BY create_time DESC LIMIT 10
</select>
// 注解方式强制刷新
@Options(flushCache = Options.FlushCachePolicy.TRUE)
List<User> selectLatestUsers();

五、验证二级缓存生效

编写测试类验证缓存是否生效:

package com.example.test;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Objects;
@Slf4j
@SpringBootTest
public class MpCacheTest {
    @Autowired
    private SqlSessionFactory sqlSessionFactory;
    @Test
    public void testSecondLevelCache() {
        // 第一次查询:缓存未命中,查数据库
        try (SqlSession session1 = sqlSessionFactory.openSession()) {
            UserMapper mapper1 = session1.getMapper(UserMapper.class);
            User user1 = mapper1.selectOne(new QueryWrapper<User>().eq("id", 1L));
            log.info("第一次查询结果:{}", user1);
        } // 会话关闭,数据存入二级缓存
        // 第二次查询:命中二级缓存
        try (SqlSession session2 = sqlSessionFactory.openSession()) {
            UserMapper mapper2 = session2.getMapper(UserMapper.class);
            User user2 = mapper2.selectOne(new QueryWrapper<User>().eq("id", 1L));
            log.info("第二次查询结果:{}", user2);
        }
    }
}

预期日志(第二次查询无 SQL 输出,证明命中缓存):

第一次查询结果:User(id=1, username=test, ...)
==>  Preparing: SELECT ... FROM t_user WHERE (id = ?)
==> Parameters: 1(Long)
<==      Total: 1
第二次查询结果:User(id=1, username=test, ...)  // 无SQL执行,命中二级缓存

六、注意事项

@CacheNamespaceRef(UserMapper.class)  // 共享UserMapper的缓存
public interface UserOrderMapper extends BaseMapper<UserOrder> {
}

总结

MyBatis-Plus 配置二级缓存的核心是:

  1. 全局开启cache-enabled: true
  2. 实体类实现Serializable
  3. 在 Mapper 中通过 XML 或注解配置<cache>/@CacheNamespace
  4. 分布式环境替换为 Redis 缓存

通过合理配置,可充分利用二级缓存减少数据库访问,同时需平衡缓存命中率与数据一致性,避免脏读问题。

到此这篇关于mybatisplus 配置二级缓存的文章就介绍到这了,更多相关mybatisplus 二级缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文