MyBatis缓存机制概述

MyBatis提供了一级缓存和二级缓存机制,用于提高数据库查询性能。一级缓存是SqlSession级别的缓存,默认开启;二级缓存是Mapper级别的缓存,需要手动配置开启。

一级缓存实现原理

一级缓存基于PerpetualCache实现,缓存存储在BaseExecutor的localCache属性中。当执行查询时,MyBatis会先从缓存中查找,若未命中才查询数据库。

// 示例:一级缓存验证
SqlSession session = sqlSessionFactory.openSession();
try {
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user1 = mapper.selectById(1);  // 第一次查询,访问数据库
    User user2 = mapper.selectById(1);  // 第二次查询,从缓存获取
    System.out.println(user1 == user2); // 输出true
} finally {
    session.close();
}

一级缓存失效场景

执行增删改操作会清空一级缓存,SqlSession关闭后缓存失效,调用clearCache方法主动清除缓存。

// 示例:缓存失效演示
SqlSession session = sqlSessionFactory.openSession();
try {
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user1 = mapper.selectById(1);  // 第一次查询
    mapper.updateUser(new User(1, "newName")); // 更新操作
    User user2 = mapper.selectById(1);  // 重新查询数据库
    System.out.println(user1 == user2); // 输出false
} finally {
    session.close();
}

二级缓存配置方式

在MyBatis配置文件中启用二级缓存,并在Mapper XML中添加<cache/>标签。

<!-- mybatis-config.xml -->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

<!-- UserMapper.xml -->
<mapper namespace="com.example.UserMapper">
    <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
</mapper>

二级缓存工作流程

二级缓存跨SqlSession共享数据,执行查询时先查二级缓存,再查一级缓存,最后访问数据库。提交事务时数据才会存入二级缓存。

// 示例:二级缓存验证
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();

缓存自定义实现

可以通过实现Cache接口创建自定义缓存,支持Redis等分布式缓存。

public class RedisCache implements Cache {
    private final String id;
    private JedisPool jedisPool;

    public RedisCache(String id) {
        this.id = id;
    }
    
    // 实现所有Cache接口方法
    // ...
}

<!-- 使用自定义缓存 -->
<cache type="com.example.RedisCache">
    <property name="host" value="redis.example.com"/>
</cache>

缓存相关注意事项

实体类必须实现Serializable接口,二级缓存不建议在高并发更新场景使用。可以通过useCache="false"关闭单个语句的缓存。

<select id="selectById" resultType="User" useCache="false">
    select * from user where id = #{id}
</select>

缓存刷新策略

设置flushCache属性控制语句执行时是否刷新缓存,默认为增删改语句刷新,查询语句不刷新。

<insert id="insertUser" parameterType="User" flushCache="true">
    insert into user values(#{id}, #{name})
</insert>

通过合理配置MyBatis缓存机制,可以显著减少数据库访问次数,但需要注意缓存一致性问题,根据业务场景选择合适的缓存策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值