说一下 mybatis 的一级缓存和二级缓存?

MyBatis 的 一级缓存二级缓存 是用来提高查询性能的缓存机制,减少数据库的访问压力。它们分别作用在不同的作用域内,缓存的级别和生存周期也有所不同。下面我将分别详细介绍一级缓存和二级缓存。

1. 一级缓存(一级缓存)

作用域:
  • 一级缓存的作用域是 SqlSession。每个 SqlSession 都有自己的一级缓存。一级缓存是 MyBatis 中默认启用的缓存,它是自动开启的,并且对于同一个 SqlSession,缓存数据会一直存在,直到 SqlSession 被关闭或提交。
工作原理:
  • 当你通过 SqlSession 执行查询时,查询结果会首先被存放到一级缓存中。一级缓存的生命周期SqlSession 的生命周期,所以对于同一个 SqlSession 中的多次查询,如果查询条件相同且数据没有发生改变,那么 MyBatis 会直接从缓存中获取查询结果,而不会再次访问数据库。
  • 缓存命中:如果你查询同样的数据,MyBatis 会直接从一级缓存中获取结果,避免了数据库的多次查询。
  • 缓存失效:当你调用 SqlSessionclearCache() 方法或 SqlSession 关闭时,一级缓存会被清空。
特点:
  • 默认开启:一级缓存是 MyBatis 默认启用的缓存。
  • 会话级缓存:一级缓存的作用域是 SqlSession,同一个 SqlSession 内的查询会共享缓存。
  • 会话结束清空SqlSession 关闭或提交时,一级缓存会被清空。
示例:
SqlSession sqlSession = sqlSessionFactory.openSession();
User user1 = sqlSession.selectOne("selectUser", 1);  // 第一次查询数据库
User user2 = sqlSession.selectOne("selectUser", 1);  // 第二次查询,使用一级缓存,避免数据库查询
System.out.println(user1 == user2);  // 输出true,表示从一级缓存获取
sqlSession.close();  // 关闭SqlSession后,一级缓存清空

2. 二级缓存(第二级缓存)

作用域:
  • 二级缓存SqlSessionFactory 级别的缓存。在 MyBatis 中,二级缓存作用于整个 SqlSessionFactory,它跨 SqlSession,也就是说,二级缓存可以在多个 SqlSession 之间共享。因此,它适用于多个数据库连接之间的缓存共享,可以减少对数据库的查询压力。
工作原理:
  • 二级缓存的开启:二级缓存默认是关闭的,需要通过配置文件或者注解显式开启。

  • 缓存行为:当你在执行 SQL 查询时,首先会检查一级缓存。如果一级缓存没有命中,则会检查二级缓存。二级缓存的查找顺序

    1. 查找一级缓存。
    2. 如果一级缓存中没有,再查找二级缓存。
    3. 如果二级缓存中也没有,才会发起数据库查询。
  • 缓存存储:在查询结果没有命中的情况下,MyBatis 会将查询结果存入二级缓存。存入缓存的条件有:

    • 查询结果不为空。
    • 查询语句的参数及查询结果可序列化(一般情况下,MyBatis 会自动处理)。
  • 缓存失效:二级缓存的失效机制相对复杂,通常是与数据的更新操作相关。例如,当数据发生变更时,二级缓存会被清除。

开启二级缓存:

为了启用二级缓存,需要在 MyBatis 配置文件中进行设置。

  1. mybatis-config.xml 配置文件中开启二级缓存
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>
  1. 在映射文件(Mapper.xml)中启用缓存

在每个 mapper 文件中,需要显式声明开启缓存:

<mapper namespace="com.example.UserMapper">
    <cache/>
    <select id="selectUser" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>
</mapper>
二级缓存存储与清理:
  • 存储方式:二级缓存可以存储在内存、文件、数据库等多种方式,具体存储的方式由自定义缓存实现。
  • 清理机制:当执行 INSERTUPDATEDELETE 操作时,MyBatis 会自动清空相应 namespace 中的缓存数据,防止脏数据被读取。
示例:
// 第一个 SqlSession 查询,查找二级缓存
SqlSession sqlSession1 = sqlSessionFactory.openSession();
User user1 = sqlSession1.selectOne("selectUser", 1);  // 查询并缓存
sqlSession1.close();  // 关闭SqlSession,缓存数据仍然存在于二级缓存

// 第二个 SqlSession 查询,查找二级缓存
SqlSession sqlSession2 = sqlSessionFactory.openSession();
User user2 = sqlSession2.selectOne("selectUser", 1);  // 从二级缓存获取
sqlSession2.close();
System.out.println(user1 == user2);  // 输出true,表示从二级缓存获取

3. 一级缓存与二级缓存的区别:

特性一级缓存(Session 缓存)二级缓存(全局缓存)
缓存范围单个 SqlSession 内部整个 SqlSessionFactory 内部
默认开启需要手动配置开启
存储数据的方式存储在 SqlSession存储在外部(如内存、磁盘等)
缓存的生命周期SqlSession 生命周期内有效直到 SqlSessionFactory 被销毁
跨 SqlSession不支持跨 SqlSession支持跨 SqlSession
缓存的清空机制SqlSession 提交或关闭时清空执行增、删、改操作时清空缓存

4. 总结:

  • 一级缓存SqlSession 级别的缓存,默认开启,缓存的数据仅在同一个 SqlSession 中有效。
  • 二级缓存SqlSessionFactory 级别的缓存,需要显式配置,跨多个 SqlSession,能有效减少对数据库的访问。
  • 在实际使用中,一级缓存和二级缓存是可以结合使用的。一级缓存通常用于短期内的数据缓存,而二级缓存则用于跨会话的长期缓存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值