【MyBatis】初步認識MyBatis的緩存,教你如何使用一級緩存和二級緩存

MyBatis包含一個非常強大的查詢緩存特性,它可以非常方便地定製和配置緩存。緩存可以極大的提升查詢效率。

MyBatis系統中默認定義了兩級緩存:一級緩存和二級緩存

  • 默認情況下,只有一級緩存開啓。(SqlSession級別的緩存, 也稱爲本地緩存)
  • 二級緩存需要手動開啓和配置,他是基於namespace級別的緩存。
  • 爲了提高擴展性,MyBatis定義了緩存接口Cache。我們可以通過實現Cache接口來自定義二級緩存

緩存作用效果

  • select 語句的結果將會被緩存。
  • insert、update 和delete語句會刷新緩存。
  • 緩存會使用最近最少使用算法(LRU)算法來清除不需要的緩存。
  • 緩存不會定時進行刷新
  • 緩存會保存列表或對象的1024個引用。
  • 緩存會被視爲讀/寫緩存,這意味着獲取到的對象並不是共享的,可以安全地被調用者修改,而不干擾其他調用者或線程所做的潛在修改。
  • 緩存只作用於cache標籤所在的映射文件中的語句

一級緩存

默認開啓,只在一個SqlSession中有效

package com.robot.dao;

import com.robot.pojo.User;
import com.robot.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class MyTest {

    @Test
    public void userTest() {
        // 從開啓sqlSession,到關閉爲止,中間都屬於一級緩存
        // 查出的內容會被緩存,在之間第二次查同樣的數據時,直接在緩存中拿,無需再去數據庫中查
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user = mapper.queryUserById(1);
        System.out.println(user);

        User user2 = mapper.queryUserById(1);
        System.out.println(user);

        sqlSession.close();
    }
}

一級緩存測試結果

由以上結果可以看到,第一次查詢出 id=1 的用戶時,執行了查詢語句以及顯示出一些信息,而第二次再次查詢 id=1 的用戶時,因爲緩存中已經有了,所以直接在緩存中取出數據即可

二級緩存

基於namespace級別的緩存,一個空間名稱,對應一個二級緩存

工作機制

  • 一個會話查詢一條數據,這個數據就會被放在當前會話的一級緩存中;
  • 如果當前會話關閉了,這個會話對應的一級緩存就沒了,但是我們想要的是,會話關閉了,一級緩存中的數據被保存到二級緩存中
  • 新的會話查詢信息,就可以從二級緩存中獲取內容;
  • 不同的mapper查出的數據會放在自己對應的緩存(map) 中;

第一步:開啓全局緩存

配置 mybatis-config.xml

<setting name="cacheEnabled" value="true"/>

第二步:在當前Mapper中使用二級緩存

配置 UserMapper.xml

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

第三步:測試

@Test
public void cache2Test() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    SqlSession sqlSession2 = MybatisUtils.getSqlSession();

    // 當一級緩存關閉時,會將緩存內容傳給二級緩存
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.queryUserById(1);
    System.out.println(user);
    sqlSession.close();

    UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
    User user2 = mapper2.queryUserById(1);
    System.out.println(user2);
    System.out.println(user==user2);
    sqlSession2.close();
}

二級緩存測試結果
以上可以看到,當第一個會話關閉後,第二次直接在緩存中查詢到了結果,因爲第一個會話關閉了,而且開啓了二級緩存,所以將一級緩存中的內容保存到了二級緩存中,當我們查詢的時候,就可以直接在緩存中取數據了

記得將實體類序列化

public class User implements Serializable {
    private int id;
    ...
}

總結

查詢的順序是:二級緩存 –> 一級緩存 –> 數據庫

先查詢二級緩存,如果命中,則直接返回給用戶,如果沒有命中,就查詢一級緩存;

如果一級緩存命中,則直接返回給用戶,如果沒有命中,就查詢數據庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章