MyBatis的緩存機制
緩存就是內存中的一個空間,通常用來提高查詢效率
MyBatis支持兩種緩存技術:一級緩存和二級緩存,其中一級緩存默認開啟,二級緩存默認關閉
一級緩存
(1)一級緩存默認開啟
(2)是一種基於SqlSession的緩存,同一個SqlSession有效,不同的SqlSession無效
(3)同一個id,可以走緩存;不同id,即使查詢的內容相同,也不會走緩存
//加載核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-cfg.xml");
//基於構建者創建工廠對象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//通過工廠創建sqlSession對象:測試一級緩存
//第一次查詢
SqlSession sqlSession1 = factory.openSession();
List<User> list1 = sqlSession1.selectList("selAll1");
System.out.println(list1);
System.out.println("*************************");
//第二次查詢
List<User> list2 = sqlSession1.selectList("selAll1");
System.out.println(list2);
sqlSession1.close();

//加載核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-cfg.xml");
//基於構建者創建工廠對象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//通過工廠創建sqlSession對象:測試一級緩存
SqlSession sqlSession1 = factory.openSession();
List<User> list1 = sqlSession1.selectList("selAll1");
System.out.println(list1);
System.out.println("***********不同id,即使內容相同,也不走緩存**************");
List<User> list2 = sqlSession1.selectList("selAll2");
System.out.println(list2);
sqlSession1.close();

//加載核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-cfg.xml");
//基於構建者創建工廠對象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//通過工廠創建sqlSession對象:測試一級緩存
SqlSession sqlSession1 = factory.openSession();
List<User> list1 = sqlSession1.selectList("selAll1");
System.out.println(list1);
// sqlSession1.close();
System.out.println("***********不是同一個sqlSession,不會走緩存**************");
SqlSession sqlSession2 = factory.openSession();
List<User> list2 = sqlSession2.selectList("selAll1");
// System.out.println(list2);

二級緩存
(1)二級緩存默認關閉
(2)是一種基於SqlSessionFactory的緩存,同一個工廠創建的SqlSession有效,不同工廠則無效
(3)需要使用時,應在指定的namespace下進行開啟
(4)<cache>標簽的屬性
eviction:緩存清除策略,常用的有LRU、FIFO、SOFT、WEAK
flushInterval:刷新間隔,需要給定一個毫秒數,表示指定時間間隔時,會自動刷新緩存
size:設置大小,默認是1024
readOnly:是否只讀(不寫入文件),默認是false,需要實體類實現序列化接口
type:用於自定義緩存機制,提供一個自定義類的全限定路徑,自定義類需要實現CaChe接口
//加載核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-cfg.xml");
//基於構建者創建工廠對象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//通過工廠創建sqlSession對象:測試二級緩存
SqlSession sqlSession1 = factory.openSession();
List<User> list1 = sqlSession1.selectList("selAll1");
System.out.println(list1);
sqlSession1.close();
System.out.println("***********同一個工廠的sqlSession,會走緩存**************");
SqlSession sqlSession2 = factory.openSession();
List<User> list2 = sqlSession2.selectList("selAll1");
System.out.println(list2);

“cache hit ratio”中文意思是“緩存命中率”。
這是一個計算機術語,終端用戶訪問加速節點時,如果該節點有緩存住了要被訪問的數據時就叫做命中,如果沒有的話需要回原服務器取,就是沒有命中。
序列化問題:
//加載核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-cfg.xml");
//基於構建者創建工廠對象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//通過工廠創建sqlSession對象:測試二級緩存
SqlSession sqlSession1 = factory.openSession();
List<User> list1 = sqlSession1.selectList("selAll1");
System.out.println(list1);
sqlSession1.close();

原因分析:
User實現類未實現序列化
為什么要實現序列化:
(1)緩存機制:將查詢結果保存到內存中
(2)內存飽滿,需要移出時,MyBatis就會自動將內存中的內容進行移除,但是文件很重要,不能,此時就需要進行序列化,以文件的形式將內容從內存保存到硬盤上,一個內容保存成文件的讀寫,必須實現序列化。
解決方案:
一:User實體類實現序列化

二:在<cache>標簽中添加readOnly屬性
表示:要求Mybatis對緩存內容只讀不寫,當需要移除的時候,直接刪除,不需要進行轉存。

