一級緩存:
也稱本地緩存,sqlSession級別的緩存。一級緩存是一直開啟的;與數據庫同一次回話期間查詢到的數據會放在本地緩存中。
如果需要獲取相同的數據,直接從緩存中拿,不會再查數據庫。
一級緩存失效的四種情況:
1.sqlSession不同。
eg:
@Test public void test01() throws IOException { SqlSessionFactory sqlSessionFactry = getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
try { Employee map = mapper.getEmployeeById(1);
Employee map2 = mapper.getEmployeeById(1);
System.out.println(map == map2);
session.commit();
}
finally { session.close(); }
}
輸出結果為true 數據庫只查詢一次,map2取緩存結果
@Test public void test01() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession session = sqlSessionFactory.openSession(); SqlSession session2 = sqlSessionFactory.openSession(); EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); EmployeeMapper mapper2 = session.getMapper(EmployeeMapper.class); try { Employee map = mapper.getEmployeeById(1); Employee map2 = mapper.getEmployeeById(1); System.out.println(map == map2); session.commit(); } finally { session.close(); } } 輸出結果為false 兩個不同的sqlSession
2.sqlSession相同,查詢條件不同。因為緩存條件不同,緩存中還沒有數據。
3.sqlSession相同,在兩次相同查詢條件中間執行過增刪改操作。(因為中間的增刪改可能對緩存中數據進行修改,所以不能用)
4.sqlSession相同,手動清空了一級緩存。
eg:
@Test public void test01() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession session = sqlSessionFactory.openSession(); EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); try { Employee map = mapper.getEmployeeById(1); session.clearCache(); Employee map2 = mapper.getEmployeeById(1); System.out.println(map == map2); session.commit(); } finally { session.close(); } } 輸出結果為false. 因為手動清清除緩存,緩存失效
二級緩存:全局緩存;基於namespace級別的緩存。一個namespace對應一個二級緩存。
工作機制:1.一個會話,查詢一條數據,這個數據會被放在當前會話的一級緩存中。
2,如果會話被關閉了,一級緩存中的數據會被保存帶二級緩存。新的會話查詢信息就會參照二級緩存。
3.sqlSession ====> Employee====>employee
sqlSession ====>DepartmentMapper=====>Department
不同的namespace查出的數據會放在自己對應的緩存中。
效果:查出的數據首先放在一級緩存中,只有一級緩存被關閉或者提交以后,一級緩存數據才會轉移到二級緩存
使用步驟:
1.開啟全局緩存配置。<settings><setting name="cacheEnabled" value="true"/></settings>
2.因為是namespace級別,需要搭配每個xxxMapper.xml中配置二級緩存<cache></cache>
<cache flushInterval="60000" size="512" readOnly="true" eviction="FIFO" type="" />
eviction:緩存的回收策略:
LRU – 最近最少使用的:移除最長時間不被使用的對象。
FIFO – 先進先出:按對象進入緩存的順序來移除它們。
SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的對象。
WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的對象。
flushInterval:緩存刷新間隔。緩存多久清空一次,默認不清空。設置一個毫秒值。
readOnly:是否只讀。true:mybatis認為所有從緩存中獲取數據的操作都是只讀操作,不會修改數據。
mybatis為了加快獲取速度,直接就會將數據在緩存中的引用交給用戶。不安全,速度快。
false:mybatis覺得獲取的數據可能被修改。mybatis會利用序列化和反序列化的技術克隆一份新的數據給用戶。安全,速度快。
size:緩存放多少元素。
type:指定自定義緩存全類名。實現cache接口即可。
3.pojo需要實現序列換接口。
和緩存相關的配置/屬性:
1.cacheEnabled:如果是false,關閉二級緩存,不關閉一級緩存。
2.每個select標簽都有userCache="true"屬性:對一級緩存沒有影響。設置為false,二級緩存失效。
3.每個增刪改標簽都有flushCache="true"屬性:一級緩存和二級緩存都會被清空。
4.在查詢標簽中flushCache="false"屬性:如果設置為true,查完會清空,一級二級緩存都會被清空,都不會用緩存。
5.sqlSession.clearn():跟session有關,只會清除一級緩存。
6.localCacheScope:<settings><setting name="localCacheScope" value="SESSION"/></settings>本地緩存作用域。
一級緩存SESSION:當前會話的所有數據保存到回話緩存中。STATEMENT:禁用一級緩存。
緩存首先一進來去查二級緩存,二級緩存沒有去找一級緩存,一級緩存沒有去找數據庫。二級緩存----->一級緩存-------->數據庫。
自定義緩存 implements Cache,重寫接口中的保存等方法,比如說保存到redis.
自定義緩存參照mybatis官網--->項目git代碼庫----->https://github.com/mybatis---->參照各種整合緩存