MyBatis 查詢結果的緩存

MyBatis的緩存指的是緩存查詢結果,當之後使用相同的sql語句、傳入相同的參數進行查詢時,可直接從mybatis本地緩存中獲取查詢結果,而沒必要查詢數據庫。sql

mybatis的緩存包括一級緩存、二級緩存,一級緩存默認是開啓的,二級緩存默認是關閉的。數據庫

 

一級緩存:緩存

SqlSession級別,在SqlSession中有一個Map,key是由sql語句、參數等信息組成的惟一值,value是查詢出來的結果對象。mybatis

 

二級緩存:app

mapper級別,同一個namespace下的mapper,有一個Map。spa

 

 

 

二級緩存能夠使這些sqlSession作到查詢結果共享。code

 

 


 

 

一級緩存

一級緩存默認是開啓的。xml

 

User user1 = mapper.queryUserById(1); User user2 = mapper.queryUserById(1);

第一次查詢時,就將查詢結果放到一級緩存中。對象

若是後續使用的sql語句相同、傳入的實參也相同,則結果對象也會相同,直接從一級緩存中獲取結果對象,再也不查詢數據庫。blog

 

 

User user1 = mapper.queryUserById(1); sqlSession.commit(); User user2 = mapper.queryUserById(1);

若是此sqlSession調用了commit()方法,會自動清空此sqlSession的一級緩存。

由於使用commit(),會將修改提交到數據庫,下一次相同的查詢,查詢結果可能變了,以前的一級緩存不能再用,因此會自動清空。

 

 

     User user1 = mapper.queryUserById(1); HashMap<String, Object> map = new HashMap<>(); map.put("username", "張三"); map.put("id", 1); mapper.updateUser(map); User user2 = mapper.queryUserById(1);

事實上,只要此sqlSession調用了<update>、<insert>、<delete>這些會修改數據庫的元素,就會清空此sqlSession的一級緩存,無論有沒有使用commit()提交。

 

 


 

 

二級緩存

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession(); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); User user1 = mapper1.queryUserById(1); System.out.println(user1); SqlSession sqlSession2 = MyBatisUtils.getSqlSession(); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user2 = mapper2.queryUserById(1); System.out.println(user2);

不使用二級緩存,會執行2次查詢。

 

 

二級緩存的使用步驟,此處以UserMapper爲例:

(1)pojo類要是可序列化的

public class User implements Serializable { //......
}

 

 

(2)在mybatis全局配置文件中開啓二級緩存

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

二級緩存默認是關閉的,須要手動開啓。

 

 

(3)在mapper映射文件中指定二級緩存的實現方式,必須顯式指定

<?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="com.chy.mapper.UserMapper">
    <cache />
    <select id="queryUserById" parameterType="integer" resultType="user"> SELECT * FROM user_tb WHERE id=#{id} </select>
    <update id="updateUser" parameterType="hashmap"> UPDATE user_tb SET username=#{username} WHERE id=#{id} </update>
</mapper>

 

完整寫法:

<cache type="perpetualCache" />

type指定二級緩存的實現方式,缺省type時默認使用mybatis自帶的perpetualCache。

 

 

(4)須要調用close()關閉sqlSession,纔會將此sqlSession的查詢結果(一級緩存)寫入到二級緩存中

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession(); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); User user1 = mapper1.queryUserById(1); System.out.println(user1); sqlSession1.close();  SqlSession sqlSession2 = MyBatisUtils.getSqlSession(); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user2 = mapper2.queryUserById(1); System.out.println(user2);

只執行1次查詢。後續使用相同sql語句、傳入相同的實參進行查詢時,直接從二級緩存中獲取結果對象。

 

 

提交修改時,會清空整個二級緩存:

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession(); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); User user1 = mapper1.queryUserById(1); System.out.println(user1); HashMap<String, Object> hashMap = new HashMap<>(); hashMap.put("username", "j"); hashMap.put("id", 1); mapper1.updateUser(hashMap);  sqlSession1.commit(); SqlSession sqlSession2 = MyBatisUtils.getSqlSession(); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user2 = mapper2.queryUserById(2); System.out.println(user2);

 

只寫了commit()、實際沒有調用<insert> | <update> | <delete>,不會清空二級緩存,反而會將以前查詢結果寫入到二級緩存。

寫了commit()、有調用<insert> | <update> | <delete>,會清空整個二級緩存。

前後調用commit()、close(),不會寫入二級緩存,由於commit()的存在,反而會清空整個二級緩存。

相關文章
相關標籤/搜索