什麼是MyBatis緩存技術

MyBatis緩存

引言

在一個Web項目中,查詢數據庫中的操做算是一個很是經常使用的操做,可是有些數據會被常常性的查詢,而每一次都去數據庫中查詢這些重複的數據,會很消耗數據庫的資源,同時使得查詢效率也很低,而 MyBatis 中就經過緩存技術來解決這樣的問題,也就是說:將一些常常查詢,而且不常常改變的,以及數據的正確對最後的結果影響不大的數據,放置在一個緩存容器中,當用戶再次查詢這些數據的時候,就沒必要再去數據庫中查詢,直接在緩存中提取就能夠了java

注:緩存能夠簡單理解爲存在於內存中的臨時數據sql

MyBatis 提供了 一級緩存和二級緩存兩種形式數據庫

  • 一級緩存:它是 SqlSession 級別的緩存,SqlSession 類的實例對象中提供了一個 HashMap 的結構,能夠用於存儲緩存數據,當咱們再次查詢同一數據的時候,MyBatis 會先去 SqlSession 中查詢,有的話,就直接調用
  • 二級緩存:是Mapper 級別的緩存,也就是說,若是多個 SqlSession 類的實例,去操做同一個Mapper配置文件中的SQL,這些實例對象能夠共用二級緩存

一級緩存

(1) 基本闡述

上面咱們總的講了一級緩存的原理,如今梳理一下它細節緩存

以一個經過 id 查詢用戶的例子來講微信

  • 第一次查詢 id 爲某個值的用戶信息時,先去 SqlSesion 的一級緩存中去尋找,若是找到了,就直接用,若是沒有找到就去數據庫中去查,而後將查到的內容存到一級緩存區域
  • 可是,若是在下一次操做中,執行了 commit 操做,也就是執行了增刪改的操做,一級緩存區域內的內容會被清空,這是爲了保證緩存中的數據的有效性,避免髒讀的產生

(2) 程序演示

演示前,我把須要準備的一些類或者表現貼出來mybatis

User表

CREATE TABLE USER (
 `id`            INT(11)NOT NULL AUTO_INCREMENT,
 `username`     VARCHAR(32) NOT NULL COMMENT '用戶名',
 `telephone`    VARCHAR(11) NOT NULL COMMENT '手機',
 `birthday`        DATETIME DEFAULT NULL COMMENT '生日',
 `gender`          CHAR(1) DEFAULT NULL COMMENT '性別',
 `address`         VARCHAR(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY  (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

User實體類

public class User implements Serializable {
    private Integer id;
    private String username;
    private String telephone;
    private Date birthday;
    private String gender;
    private String address;
    ...... 請補充 get set 方法
}

UserMapper接口

public interface UserMapper {
    /**
     * 根據id查詢用戶信息
     * @param userId
     * @return
     */
    User findById(Integer userId);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.ideal.mapper.UserMapper">
    <!-- 根據id查詢用戶 -->
    <select id="findById" parameterType="INT" resultType="user">
       SELECT * FROM user where id = #{uid}
    </select>
</mapper>

測試方法app

/**
* 測試查詢全部
*/
@Test
public void testFirstLevelCache() {
    User user1 = userMapper.findById(16);
    System.out.println(user1);
    User user2 = userMapper.findById(16);
    System.out.println(user2);
    System.out.println(user1 == user2);
}

執行效果

能夠很明顯的看到,當咱們在同一個 sqlSession的狀況下,當咱們第一次查詢 id 值爲 16 的用戶時,從數據庫中確實查詢到了數據,而第二次查詢的時候,卻沒有任何日誌的數據,而同時咱們能夠看到,經過輸出語句,看到兩個對象是徹底相同的,這也就意味着,第二次查詢不是從數據庫查詢出來的,而是從緩存中ide

二級緩存

(1) 基本闡述

經過上面的簡單認識,咱們認識到一級緩存是基於同一個 SqlSession的,可是有時候因爲方法封裝的緣由,或者在查詢完,SqlSession 對象會關閉,一級緩存就清空了,會致使沒法從中獲取內容測試

二級緩存的能夠幫咱們解決一級緩存沒法使用的狀況,前面已經說過二級緩存是Mapper 級別的緩存,多個SqlSession類的實例對象加載同一個Mapper配置文件,並執行其中SQL配置的收,他們就共享同一個 Mapper 緩存,執行流程也與一級緩存基本是一致的ui

  • 查詢時,先去Mapper緩存區去找這個值,若是找不到,就去數據庫查,而後將查詢到的結果存儲到緩存中,等下次使用
  • 當某個 SqlSession 類的實例對象執行了增刪改操做時,二級緩存會被清空

還依據剛開始準備的代碼,咱們直接寫出其測試代碼,看看在不一樣的 SqlSession 下,加載同一個Mapper的SQL是否會看到二級緩存的效果

(2) 程序演示

測試代碼

@Test
public void testSecondLevelCache() {
    SqlSession sqlSession1 = factory.openSession();
    UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
    User user1 = mapper1.findById(16);
    sqlSession1.close();

    SqlSession sqlSession2 = factory.openSession();
    UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
    User user2 = mapper2.findById(16);
    sqlSession1.close();

    System.out.println(user1 == user2);
}

第一次執行效果

看完測試代碼,咱們發現,SQL執行了兩次,很顯然,沒有達到了咱們的指望,那麼是哪裏不對呢?

答案是,在MyBatis中一級緩存是默認開啓的,而二級緩存則須要進行配置開啓

要開啓二級緩存,須要進行兩個操做步驟

  • ①:在總配置文件 SqlMapConfig.xml 中配置 setting屬性
  • ②:在SQL映射文件中開啓二級緩存

經過官網的文檔,能夠看到,默認值就是true,因此,不配置也是能夠的,不過咱們仍是先給出來

修改 SqlMapConfig.xml

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

修改 UserMapper.xml

只須要在文件中添加一個 cache標籤就能夠了,很是簡單

<cache/>

執行效果

還有一個須要注意的地方,那就是咱們最後作的判斷 System.out.println(user1 == user2); 爲何的到的結果倒是 false呢?

這是由於,在二級緩存中,存入的是值,而不是對象,當須要使用的時候,會建立出新的用戶,而後將值傳入,因此這裏是不等的

不過使用二級緩存的時候,必定要謹慎,由於有時候不一樣的namespace下的 SQL配置中可能緩存着相同的數據,如咱們上面的例子,UserMapper.xml 中有關於 user表的操做,可是若是在其餘 Mmpper.xml 中仍然有針對 user 單表的操做,這會致使兩方數據不同,若是在咱們 UserMapper.xml 進行了刷新緩存,可是另外一個Mapper.xml 中可能仍有效,因此可能會出現錯誤

結尾

若是文章中有什麼不足,歡迎你們留言交流,感謝朋友們的支持!

若是能幫到你的話,那就來關注我吧!若是您更喜歡微信文章的閱讀方式,能夠關注個人公衆號

在這裏的咱們素不相識,卻都在爲了本身的夢而努力 ❤

一個堅持推送原創開發技術文章的公衆號:理想二旬不止

相關文章
相關標籤/搜索