缓存在哪里_什么是MyBatis缓存技术
MyBatis緩存
引言
在一個Web項目中,查詢數(shù)據(jù)庫中的操作算是一個非常常用的操作,但是有些數(shù)據(jù)會被經(jīng)常性的查詢,而每一次都去數(shù)據(jù)庫中查詢這些重復(fù)的數(shù)據(jù),會很消耗數(shù)據(jù)庫的資源,同時使得查詢效率也很低,而 MyBatis 中就通過緩存技術(shù)來解決這樣的問題,也就是說:將一些經(jīng)常查詢,并且不經(jīng)常改變的,以及數(shù)據(jù)的正確對最后的結(jié)果影響不大的數(shù)據(jù),放置在一個緩存容器中,當(dāng)用戶再次查詢這些數(shù)據(jù)的時候,就不必再去數(shù)據(jù)庫中查詢,直接在緩存中提取就可以了
注:緩存可以簡單理解為存在于內(nèi)存中的臨時數(shù)據(jù)
MyBatis 提供了 一級緩存和二級緩存兩種形式
- 一級緩存 :它是 SqlSession 級別的緩存,SqlSession 類的實例對象中提供了一個 HashMap 的結(jié)構(gòu),可以用于存儲緩存數(shù)據(jù),當(dāng)我們再次查詢同一數(shù)據(jù)的時候,MyBatis 會先去 SqlSession 中查詢,有的話,就直接調(diào)用
- 二級緩存 :是Mapper 級別的緩存,也就是說,如果多個 SqlSession 類的實例,去操作同一個Mapper配置文件中的SQL,這些實例對象可以共用二級緩存
一級緩存
(1) 基本闡述
上面我們總的講了一級緩存的原理,現(xiàn)在梳理一下它細(xì)節(jié)
以一個通過 id 查詢用戶的例子來說
- 第一次查詢 id 為某個值的用戶信息時,先去 SqlSesion 的一級緩存中去尋找,如果找到了,就直接用,如果沒有找到就去數(shù)據(jù)庫中去查,然后將查到的內(nèi)容存到一級緩存區(qū)域
- 但是,如果在下一次操作中,執(zhí)行了 commit 操作,也就是執(zhí)行了增刪改的操作,一級緩存區(qū)域內(nèi)的內(nèi)容會被清空,這是為了保證緩存中的數(shù)據(jù)的有效性,避免臟讀的產(chǎn)生
(2) 程序演示
演示前,我把需要準(zhǔn)備的一些類或者表現(xiàn)貼出來
User表
CREATE TABLE USER ( `id` INT(11)NOT NULL AUTO_INCREMENT, `username` VARCHAR(32) NOT NULL COMMENT '用戶名', `telephone` VARCHAR(11) NOT NULL COMMENT '手機(jī)', `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; ...... 請補(bǔ)充 get set 方法}UserMapper接口
public interface UserMapper { /** * 根據(jù)id查詢用戶信息 * @param userId * @return */ User findById(Integer userId);}UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?> SELECT * FROM user where id = #{uid}測試方法
/*** 測試查詢所有*/@Testpublic 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);}執(zhí)行效果
可以很明顯的看到,當(dāng)我們在同一個 sqlSession的情況下,當(dāng)我們第一次查詢 id 值為 16 的用戶時,從數(shù)據(jù)庫中確實查詢到了數(shù)據(jù),而第二次查詢的時候,卻沒有任何日志的數(shù)據(jù),而同時我們可以看到,通過輸出語句,看到兩個對象是完全相同的,這也就意味著,第二次查詢不是從數(shù)據(jù)庫查詢出來的,而是從緩存中
二級緩存
(1) 基本闡述
通過上面的簡單認(rèn)識,我們認(rèn)識到一級緩存是基于同一個 SqlSession的,但是有時候由于方法封裝的原因,或者在查詢完,SqlSession 對象會關(guān)閉,一級緩存就清空了,會導(dǎo)致無法從中獲取內(nèi)容
二級緩存的可以幫我們解決一級緩存無法使用的情況,前面已經(jīng)說過二級緩存是Mapper 級別的緩存,多個SqlSession類的實例對象加載同一個Mapper配置文件,并執(zhí)行其中SQL配置的收,他們就共享同一個 Mapper 緩存,執(zhí)行流程也與一級緩存基本是一致的
- 查詢時,先去Mapper緩存區(qū)去找這個值,如果找不到,就去數(shù)據(jù)庫查,然后將查詢到的結(jié)果存儲到緩存中,等下次使用
- 當(dāng)某個 SqlSession 類的實例對象執(zhí)行了增刪改操作時,二級緩存會被清空
還依據(jù)剛開始準(zhǔn)備的代碼,我們直接寫出其測試代碼,看看在不同的 SqlSession 下,加載同一個Mapper的SQL是否會看到二級緩存的效果
(2) 程序演示
測試代碼
@Testpublic 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);}第一次執(zhí)行效果
看完測試代碼,我們發(fā)現(xiàn),SQL執(zhí)行了兩次,很顯然,沒有達(dá)到了我們的期望,那么是哪里不對呢?
答案是,在MyBatis中一級緩存是默認(rèn)開啟的,而二級緩存則需要進(jìn)行配置開啟
要開啟二級緩存,需要進(jìn)行兩個操作步驟
- ①:在總配置文件 SqlMapConfig.xml 中配置 setting屬性
- ②:在SQL映射文件中開啟二級緩存
通過官網(wǎng)的文檔,可以看到,默認(rèn)值就是true,所以,不配置也是可以的,不過我們還是先給出來
修改 SqlMapConfig.xml
修改 UserMapper.xml
只需要在文件中添加一個 cache標(biāo)簽就可以了,非常簡單
執(zhí)行效果
還有一個需要注意的地方,那就是我們最后做的判斷 System.out.println(user1 == user2); 為什么的到的結(jié)果卻是 false呢?
這是因為,在二級緩存中,存入的是值,而不是對象,當(dāng)需要使用的時候,會創(chuàng)建出新的用戶,然后將值傳入,所以這里是不等的
不過使用二級緩存的時候,一定要謹(jǐn)慎,因為有時候不同的namespace下的 SQL配置中可能緩存著相同的數(shù)據(jù),如我們上面的例子,UserMapper.xml 中有關(guān)于 user表的操作,但是如果在其他 Mmpper.xml 中仍然有針對 user 單表的操作,這會導(dǎo)致兩方數(shù)據(jù)不一樣,如果在我們 UserMapper.xml 進(jìn)行了刷新緩存,但是另一個Mapper.xml 中可能仍有效,所以可能會出現(xiàn)錯誤
總結(jié)
以上是生活随笔為你收集整理的缓存在哪里_什么是MyBatis缓存技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 四元数左乘右乘_四元数、欧拉角学习笔记个
- 下一篇: 现在银行etl还要做拉链表吗_hive