面試官:說一下MyBatis緩存機(jī)制?
MyBatis 的緩存機(jī)制屬于本地緩存,適用于單機(jī)系統(tǒng),它的作用是減少數(shù)據(jù)庫的查詢次數(shù),提高系統(tǒng)性能。
MyBaits 中包含兩級(jí)本地緩存:
- 一級(jí)緩存:SqlSession 級(jí)別的,是 MyBatis 自帶的緩存功能,默認(rèn)開啟,并且無法關(guān)閉,因此當(dāng)有兩個(gè) SqlSession 訪問相同的 SQL 時(shí),一級(jí)緩存也不會(huì)生效,需要查詢兩次數(shù)據(jù)庫。
- 二級(jí)緩存:Mapper 級(jí)別的,只要是同一個(gè) Mapper,無論使用多少個(gè) SqlSession 來操作,數(shù)據(jù)都是共享的,多個(gè)不同的 SqlSession 可以共用二級(jí)緩存,MyBatis 二級(jí)緩存默認(rèn)是關(guān)閉的,需要使用時(shí)可手動(dòng)開啟,二級(jí)緩存也可以使用第三方的緩存,比如,使用 Ehcache 作為二級(jí)緩存。
一級(jí)緩存 VS 二級(jí)緩存
一級(jí)緩存和二級(jí)緩存的主要區(qū)別如下:
- 一級(jí)緩存是 SqlSession 級(jí)別的緩存,它的作用域是同一個(gè) SqlSession,同一個(gè) SqlSession 中的多次查詢會(huì)共享同一個(gè)緩存。二級(jí)緩存是 Mapper 級(jí)別的緩存,它的作用域是同一個(gè) Mapper,同一個(gè) Mapper 中的多次查詢會(huì)共享同一個(gè)緩存。
- 一級(jí)緩存是默認(rèn)開啟的,不需要手動(dòng)配置。二級(jí)緩存需要手動(dòng)配置,需要在 Mapper.xml 文件中添加標(biāo)簽。
- 一級(jí)緩存的生命周期是和 SqlSession 一樣長的,當(dāng) SqlSession 關(guān)閉時(shí),一級(jí)緩存也會(huì)被清空。二級(jí)緩存的生命周期是和 MapperFactory 一樣長的,當(dāng)應(yīng)用程序關(guān)閉時(shí),二級(jí)緩存也會(huì)被清空。
- 一級(jí)緩存只能用于同一個(gè) SqlSession 中的多次查詢,不能用于跨 SqlSession 的查詢。二級(jí)緩存可以用于跨 SqlSession 的查詢,多個(gè) SqlSession 可以共享同一個(gè)二級(jí)緩存。
- 一級(jí)緩存是線程私有的,不同的 SqlSession 之間的緩存數(shù)據(jù)不會(huì)互相干擾。二級(jí)緩存是線程共享的,多個(gè) SqlSession 可以共享同一個(gè)二級(jí)緩存,需要考慮線程安全問題。
開啟二級(jí)緩存
MyBatis 一級(jí)緩存是自帶的緩存,默認(rèn)開啟,且無法關(guān)閉。而二級(jí)緩存默認(rèn)是關(guān)閉的,因此我們只需要掌握二級(jí)緩存的開啟即可。二級(jí)緩存開啟需要兩步:
- 在 mapper xml 中添加標(biāo)簽。
- 在需要緩存的標(biāo)簽上設(shè)置 useCache="true"(最新版本中,可以省略此步驟)。
完整示例實(shí)現(xiàn)如下:
<?xml versinotallow="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.mybatis.demo.mapper.StudentMapper">
<cache/>
<select id="getStudentCount" resultType="Integer" useCache="true">
select count(*) from student
</select>
</mapper>
編寫單元測(cè)試代碼:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class StudentMapperTest {
@Autowired
private StudentMapper studentMapper;
@Test
void getStudentCount() {
int count = studentMapper.getStudentCount();
System.out.println("查詢結(jié)果:" + count);
int count2 = studentMapper.getStudentCount();
System.out.println("查詢結(jié)果2:" + count2);
}
}
執(zhí)行以上單元測(cè)試的執(zhí)行結(jié)果如下:
從以上結(jié)果可以看出,兩次查詢雖然使用了不同的 SqlSession,但第二次查詢使用了緩存,并未查詢數(shù)據(jù)庫。
小結(jié)
MyBatis 的緩存機(jī)制屬于本地緩存,適用于單機(jī)系統(tǒng),它的作用是減少數(shù)據(jù)庫的查詢次數(shù),提高系統(tǒng)性能。MyBatis 本地緩存有兩類:一級(jí)緩存 SqlSession 級(jí)別,默認(rèn)開啟不能關(guān)閉,二級(jí)緩存 Mapper 級(jí)別,默認(rèn)關(guān)閉,可以通過在 XML 中添加標(biāo)簽開啟。