您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“MyBatis中的一級和二級緩存怎么用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“MyBatis中的一級和二級緩存怎么用”這篇文章吧。
緩存是存在內存中的臨時數據,通過將我們 「經常查詢但不常變的數據」 放在內存中,當我們查詢數據時就不在需要從磁盤讀取,而只需要從緩存中查詢即可,大大提升了查詢的效率,解決了高并發系統的性能問題。
既然我們可以直接從數據庫中查詢數據,那為什么還要需要緩存呢?通過使用緩存,我們能夠減少和數據庫之間的交互頻率,減少系統開銷,從而提高系統的效率。
MyBatis 內置了一個強大的事務性查詢緩存機制,通過它能夠十分方便的配置和定制。默認情況下,MyBatis 默認定義了兩級緩存,而且為了提高擴展性,定義了緩存接口 Cache
,我們能十分方便的實現 Cache
接口來自定義二級緩存。
SqlSession
級別的緩存);namespace
級別的緩存,需要我們手動進行開啟和配置;也叫 「本地緩存」,在與數據庫同一次會話期間查詢到的數據放在本地緩存,當要再次獲取相同數據時,直接從緩存獲取即可,不用再次和數據庫交互。
每個 SqlSession
中都有一個 Executor
,每個 Executor
中又有一個 LocalCache
,當我們進行查詢操作時,MyBatis 根據當前執行的語句生成 MapperdStatement
,然后在 Local Cache
中進行查詢,如果存在(命中),直接返回給用戶。若緩存中不存在(未命中),則和數據庫交互查詢數據,將結果寫入 Local Cache
,同時返回給用戶。
一級緩存即 SqlSession
級別的緩存,和我們之前的 CURD 操作差不多;
@Select("select * from user where id=#{id}")
User queryUserById(@Param("id") int id);
@Test
public void testQueryUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user1 = mapper.queryUserById(1);
System.out.println(user1);
User user2 = mapper.queryUserById(1);
System.out.println(user2);
System.out.println(user1 == user2);
sqlSession.close();
}
通過結果可以看出,由于是在一次會話期間內(SqlSession
級別),所以此時的 SQL 語句只查詢了一次,當第二次獲取相同結果時,直接從緩存中取結果即可,也就解釋了為什么 user1
和 user2
指向的是同一個對象;
一級緩存是默認一直開啟的,我們是關閉不了的。但是有時候一級緩存會出現失效的情況,主要可能是如下幾種原因導致;
SqlSession
中緩存獨立」當我們使用不同的 SqlSession
時,有多少個 SqlSession
就需要向數據庫發起多少次查詢請求。
@Test
public void testQueryUserById() {
SqlSession sqlSession1 = MybatisUtil.getSqlSession();
UserDao mapper1 = sqlSession1.getMapper(UserDao.class);
SqlSession sqlSession2 = MybatisUtil.getSqlSession();
UserDao mapper2 = sqlSession2.getMapper(UserDao.class);
User user1 = mapper1.queryUserById(1);
System.out.println(user1);
User user2 = mapper2.queryUserById(1);
System.out.println(user2);
System.out.println(user1 == user2);
sqlSession1.close();
sqlSession2.close();
}
當位于同一個 SqlSession
,但查詢條件不同時,也會導致緩存失效;
@Test
public void testQueryUserById1() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = mapper.queryUserById(1);
System.out.println(user);
User user2 = mapper.queryUserById(2);
System.out.println(user2);
System.out.println(user == user2);
sqlSession.close();
}
假如在同一 SqlSession
中,在兩次查詢之間進行了其他的增刪改等操作,當第二次查詢進行時,就會重新執行 SQL 語句,導致緩存失效;
@Test
public void testQueryUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = mapper.queryUserById(1);
System.out.println(user);
mapper.updateUser(new User(2,"小玉","8349823"));
User user2 = mapper.queryUserById(1);
System.out.println(user2);
System.out.println(user == user2);
sqlSession.close();
}
當 SqlSession
相同時,如果我們手動清除了緩存,那么也會導致緩存失效的情況出現。
@Test
public void testQueryUserById1() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = mapper.queryUserById(1);
System.out.println(user);
// 手動清除緩存
sqlSession.clearCache();
User user2 = mapper.queryUserById(1);
System.out.println(user2);
System.out.println(user == user2);
sqlSession.close();
}
也叫 「全局緩存」,基于 namespace
的緩存,一個 namespace
對應一個二級緩存。
一級緩存的最大共享范圍是一個 SqlSession
內部,若多個 SqlSession
之間要共享緩存,則需要用二級緩存。二級緩存一旦開啟,將會有多個 CachingExecutor
來裝飾 Executor
,進入一級緩存的查詢流程之前,先在 CachingExecutor
中進行二級緩存的查詢,如上圖。此時數據的查詢流程是:
?二級緩存 -> 一級緩存 -> 數據庫
?
要使用二級緩存,通常需要有如下步驟:
mybatis-config.xml
)中開啟二級緩存;<setting name="cacheEnabled" value="true"/>
xxxMapper.xml
中配置二級緩存;<cache/>
配置之后,xxxMapper.xml
文件中的 select
語句將會被緩存,而 insert、update、delete
則會刷新緩存。此外還可以設置自定義屬性值來修改默認屬性;
屬性 | 說明 |
---|---|
eviction | 清除策略 |
flushInterval | 刷新間隔,單位是 ms |
size | 引用數目,默認為 1024 |
readOnly | 默認為 false |
而清除策略也主要有如下 4 種:
清除策略 | 說明 |
---|---|
LRU | 「最近最少使用」:移除最長時間不被使用的對象 |
FIFO | 「先進先出」:按對象進入緩存的順序來移除 |
SOFT | 「軟引用」:基于垃圾回收器狀態和軟引用規則移除對象 |
WEAK | 「弱引用」:更積極地基于垃圾回收器狀態和若引用規則移除對象 |
@Test
public void testGetUserByPassword() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
SqlSession sqlSession2 = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
UserDao mapper2 = sqlSession.getMapper(UserDao.class);
User user = mapper.getUserByPassword("1234567");
System.out.println(user);
User user2 = mapper2.getUserByPassword("1234567");
System.out.println(user2);
System.out.println(user==user2);
sqlSession.close();
sqlSession2.close();
}
根據結果可以看出,此時的二級緩存已經生效。若是未生效,則會和一級緩存中的結果一致,兩者指向不同的對象,但此時兩個引用指向同一對象,說明二級緩存成功。
以上是“MyBatis中的一級和二級緩存怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。