以下是MyBatis緩存配置的完整示例,包含一級緩存、二級緩存、自定義緩存策略等核心場景,并附詳細注釋和總結表格:
1. 一級緩存(默認開啟)
// 使用同一SqlSession執行兩次查詢,自動命中一級緩存
try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper mapper = session.getMapper(UserMapper.class);User user1 = mapper.selectById(1); // 第一次查詢(數據庫)User user2 = mapper.selectById(1); // 第二次查詢(緩存命中)System.out.println(user1 == user2); // 輸出:true
}
2. 二級緩存配置(XML方式)
<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper"><!-- 開啟二級緩存 --><cache eviction="FIFO" <!-- 緩存回收策略:先進先出 -->flushInterval="60000" <!-- 緩存刷新間隔:60秒 -->size="512" <!-- 緩存最大條目數 -->readOnly="false"/> <!-- 是否只讀(false允許對象修改) --><select id="selectById" resultType="User">SELECT * FROM user WHERE id = #{id}</select>
</mapper>
3. 二級緩存注解配置
// UserMapper.java
@Mapper
@CacheNamespace(implementation = EhcacheCache.class, // 使用第三方緩存(如Ehcache)eviction = CacheNamespaceEvictionPolicy.FIFO,flushInterval = 60000,size = 512,readWrite = true
)
public interface UserMapper {User selectById(Integer id);
}
4. 緩存對象序列化配置
// User實體類需要實現Serializable接口
public class User implements Serializable {private Integer id;private String name;private transient Integer age; // transient字段不參與序列化// 省略getter/setter
}
5. 緩存手動操作示例
// 清除指定對象緩存
sqlSession.clearCache(); // 清除一級緩存
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.selectById(1);
sqlSession.commit(); // 觸發二級緩存更新// 清除二級緩存
((org.apache.ibatis.session.Configuration)sqlSession.getConfiguration()).getCache("com.example.mapper.UserMapper").clear();
關鍵技術點總結表
場景 | 配置方式 | 適用情況 | 核心注釋 |
---|---|---|---|
一級緩存 | 默認開啟(SqlSession級別) | 單次業務操作內多次查詢 | 不需要配置,關閉需調用sqlSession.clearCache() |
二級緩存 | <cache> 標簽或@CacheNamespace | 跨SqlSession的全局緩存 | 必須實現Serializable,需在Mapper配置中顯式開啟 |
緩存回收策略 | eviction="FIFO/LRU/SID" | 控制內存占用 | LRU(最近最少使用)最常用 |
緩存過期 | flushInterval="60000" | 定時刷新緩存 | 毫秒單位,配合數據庫數據變更頻率設置 |
緩存容量 | size="512" | 控制內存使用 | 根據業務數據量合理設置 |
緩存可寫性 | readOnly="false" | 允許修改緩存對象 | readOnly為true時返回對象為不可變副本 |
第三方緩存 | implementation=EhcacheCache | 需要分布式緩存 | 需引入對應依賴并配置緩存實現類 |
6. 核心配置注意事項:
- 序列化要求:被緩存的對象必須實現
Serializable
接口 - 事務邊界:SqlSession關閉或提交(commit)會刷新二級緩存
- 并發控制:
readOnly="true"
可避免并發修改問題 - 緩存失效:數據更新操作(insert/update/delete)會自動清除相關緩存
- 命名空間:二級緩存按Mapper命名空間隔離,需確保唯一性
7. 性能驗證示例
// 驗證二級緩存跨SqlSession命中
try (SqlSession session1 = sqlSessionFactory.openSession()) {UserMapper mapper1 = session1.getMapper(UserMapper.class);User user1 = mapper1.selectById(1); // 數據庫查詢
}try (SqlSession session2 = sqlSessionFactory.openSession()) {UserMapper mapper2 = session2.getMapper(UserMapper.class);User user2 = mapper2.selectById(1); // 二級緩存命中System.out.println(user1.equals(user2)); // 輸出:true(值相等但對象不同)
}
需要進一步擴展場景(如條件緩存、自定義緩存實現)可補充說明。