侧边栏壁纸
博主头像
拾荒的小海螺博主等级

只有想不到的,没有做不到的

  • 累计撰写 194 篇文章
  • 累计创建 19 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

JAVA:MyBatis 缓存机制详解的技术指南

拾荒的小海螺
2024-11-22 / 0 评论 / 1 点赞 / 8 阅读 / 5845 字

1、简述

MyBatis是Java开发中常用的持久层框架之一,通过面向对象的方式操作数据库。为了提高系统性能,MyBatis提供了两级缓存机制:一级缓存(本地缓存)和二级缓存(全局缓存)。本文将详细讲解MyBatis缓存机制的使用原理、配置方法,并通过示例展示如何合理地使用缓存优化数据访问效率。

image-ggig.png

2、基础原理

2.1 一级缓存

  • 作用范围:一级缓存是基于SqlSession级别的缓存,即在同一个SqlSession中执行的相同SQL语句将会从缓存中获取结果,而不会再去查询数据库。
  • 存储方式:一级缓存的默认存储机制是基于HashMap实现的。
  • 特点:默认开启,无法跨SqlSession共享数据,查询范围有限。

2.2 二级缓存

  • 作用范围:二级缓存是基于Mapper级别的缓存,即同一个命名空间的Mapper都可以共享二级缓存。
  • 存储方式:MyBatis默认使用PerpetualCache作为二级缓存,使用HashMap进行存储。
  • 特点:二级缓存是可选的,需要在配置文件中开启,支持多个SqlSession共享同一数据,能够有效减少数据库查询次数。

3、一级缓存的使用

一级缓存默认开启,无需额外配置。当执行同一查询时,MyBatis会先检查一级缓存,若存在结果则直接返回缓存数据,否则才会执行SQL查询数据库。

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.example.mapper.UserMapper;
import com.example.model.User;

public class MyBatisCacheDemo {

    public static void main(String[] args) {
        SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();

        try (SqlSession session = sqlSessionFactory.openSession()) {
            UserMapper userMapper = session.getMapper(UserMapper.class);

            // 第一次查询
            User user1 = userMapper.selectUserById(1);
            System.out.println("第一次查询:" + user1);

            // 第二次查询,触发一级缓存
            User user2 = userMapper.selectUserById(1);
            System.out.println("第二次查询(来自缓存):" + user2);

            // 判断是否为同一对象
            System.out.println("是否为同一对象:" + (user1 == user2));  // true
        }
    }
}

注意:如果执行了session.commit()、session.close()、session.clearCache()等操作,一级缓存将会失效。

4、二级缓存的配置与使用

MyBatis默认关闭二级缓存,需要在mybatis-config.xml或Mapper映射文件中开启。

4.1 在全局配置文件中开启二级缓存

在mybatis-config.xml中增加true,如:

<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

4.2 在Mapper XML文件中配置二级缓存

在具体的Mapper文件中加入标签来启用二级缓存。

<mapper namespace="com.example.mapper.UserMapper">
    <cache/>
  
    <select id="selectUserById" parameterType="int" resultType="com.example.model.User">
        SELECT * FROM user WHERE id = #{id}
    </select>
</mapper>

4.3 使用二级缓存示例

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.example.mapper.UserMapper;
import com.example.model.User;

public class MyBatisCacheDemo {

    public static void main(String[] args) {
        SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();

        // 第一次查询,开启第一个SqlSession
        try (SqlSession session1 = sqlSessionFactory.openSession()) {
            UserMapper userMapper1 = session1.getMapper(UserMapper.class);
            User user1 = userMapper1.selectUserById(1);
            System.out.println("第一次查询:" + user1);
        } // SqlSession关闭,触发二级缓存存储

        // 第二次查询,开启新的SqlSession
        try (SqlSession session2 = sqlSessionFactory.openSession()) {
            UserMapper userMapper2 = session2.getMapper(UserMapper.class);
            User user2 = userMapper2.selectUserById(1);
            System.out.println("第二次查询(来自二级缓存):" + user2);

            // 判断是否为同一对象
            System.out.println("是否为同一对象:" + (user1 == user2));  // true
        }
    }
}

5、缓存失效的场景

在以下情况下,MyBatis的缓存将会失效:

  • 增删改操作:每当执行INSERT、UPDATE或DELETE操作后,一级缓存和二级缓存都会失效。
  • 手动清空缓存:可以通过SqlSession.clearCache()方法手动清空一级缓存。
  • 不同SqlSession:一级缓存仅作用于当前SqlSession,不同SqlSession之间无法共享一级缓存。
  • 其他影响因素:MyBatis中mapper.xml文件中的flushCache配置项等也会影响缓存策略。

缓存的优缺点分析:

  • 优点
    提升性能:缓存机制减少了数据库的交互次数,提升了查询效率。
    简化数据共享:特别是二级缓存,多个SqlSession可以共享数据,适合不经常变动的数据。
  • 缺点
    缓存不一致:数据库数据变动后,可能会造成缓存数据不一致的问题。
    占用内存:大量的数据缓存可能会导致内存占用过高。
    适用场景有限:频繁变动的数据不适合缓存。

6、总结

MyBatis的缓存机制是一种有效的数据访问优化方案。通过一级缓存和二级缓存,开发者可以显著减少数据库查询次数,提升系统的性能。在实际使用中,需要合理配置和使用缓存机制,特别是在数据变动频繁的情况下,可以适当关闭缓存或手动清空缓存,保证数据的一致性。

MyBatis缓存的使用场景建议:

  • 适用于读取频率高且修改较少的数据,如产品信息、用户基本资料等。
  • 对于频繁变更的数据,如订单、库存信息等,建议关闭缓存,以避免缓存不一致的问题。

通过合适的缓存配置和控制策略,MyBatis缓存机制可以为系统带来显著的性能提升。希望本文的示例和介绍对您在项目中使用MyBatis缓存有所帮助。

1

评论区