在一個Web項目中,查詢數據庫中的操做算是一個很是經常使用的操做,可是有些數據會被常常性的查詢,而每一次都去數據庫中查詢這些重複的數據,會很消耗數據庫的資源,同時使得查詢效率也很低,而 MyBatis 中就經過緩存技術來解決這樣的問題,也就是說:將一些常常查詢,而且不常常改變的,以及數據的正確對最後的結果影響不大的數據,放置在一個緩存容器中,當用戶再次查詢這些數據的時候,就沒必要再去數據庫中查詢,直接在緩存中提取就能夠了java
注:緩存能夠簡單理解爲存在於內存中的臨時數據sql
MyBatis 提供了 一級緩存和二級緩存兩種形式數據庫
上面咱們總的講了一級緩存的原理,如今梳理一下它細節緩存
以一個經過 id 查詢用戶的例子來講微信
演示前,我把須要準備的一些類或者表現貼出來mybatis
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;
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 方法 }
public interface UserMapper { /** * 根據id查詢用戶信息 * @param userId * @return */ User findById(Integer userId); }
<?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
經過上面的簡單認識,咱們認識到一級緩存是基於同一個 SqlSession的,可是有時候因爲方法封裝的緣由,或者在查詢完,SqlSession 對象會關閉,一級緩存就清空了,會致使沒法從中獲取內容測試
二級緩存的能夠幫咱們解決一級緩存沒法使用的狀況,前面已經說過二級緩存是Mapper 級別的緩存,多個SqlSession類的實例對象加載同一個Mapper配置文件,並執行其中SQL配置的收,他們就共享同一個 Mapper 緩存,執行流程也與一級緩存基本是一致的ui
還依據剛開始準備的代碼,咱們直接寫出其測試代碼,看看在不一樣的 SqlSession 下,加載同一個Mapper的SQL是否會看到二級緩存的效果
@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中一級緩存是默認開啓的,而二級緩存則須要進行配置開啓
要開啓二級緩存,須要進行兩個操做步驟
經過官網的文檔,能夠看到,默認值就是true,因此,不配置也是能夠的,不過咱們仍是先給出來
<settings> <setting name="cacheEnabled" value="true"/> </settings>
只須要在文件中添加一個 cache標籤就能夠了,很是簡單
<cache/>
還有一個須要注意的地方,那就是咱們最後作的判斷 System.out.println(user1 == user2);
爲何的到的結果倒是 false呢?
這是由於,在二級緩存中,存入的是值,而不是對象,當須要使用的時候,會建立出新的用戶,而後將值傳入,因此這裏是不等的
不過使用二級緩存的時候,必定要謹慎,由於有時候不一樣的namespace下的 SQL配置中可能緩存着相同的數據,如咱們上面的例子,UserMapper.xml 中有關於 user表的操做,可是若是在其餘 Mmpper.xml 中仍然有針對 user 單表的操做,這會致使兩方數據不同,若是在咱們 UserMapper.xml 進行了刷新緩存,可是另外一個Mapper.xml 中可能仍有效,因此可能會出現錯誤
若是文章中有什麼不足,歡迎你們留言交流,感謝朋友們的支持!
若是能幫到你的話,那就來關注我吧!若是您更喜歡微信文章的閱讀方式,能夠關注個人公衆號
在這裏的咱們素不相識,卻都在爲了本身的夢而努力 ❤一個堅持推送原創開發技術文章的公衆號:理想二旬不止