mybatis中的緩存問題

關於mybatis基礎咱們前面幾篇博客已經介紹了不少了,今天咱們來講一個簡單的問題,那就是mybatis中的緩存問題。mybatis自己對緩存提供了支持,可是若是咱們沒有進行任何配置,那麼默認狀況下系統只開啓了一級緩存,一級緩存就是同一個SqlSession執行的相同查詢是會進行緩存的,OK,那麼今天咱們就來看看這些緩存,並簡單驗證下。java

系統默認開啓了一級緩存

這個緩存系統默認狀況下是開啓的,當咱們獲取到一個SqlSession對象以後,若是調用SqlSession中的同一個方法查詢同一條數據,那麼第二次查詢將不會去數據庫中查詢,由於第一次查詢有緩存,直接調用緩存數據便可,除非緩存超時或者咱們明確聲明數據要刷新,不然都是直接調用緩存數據。OK,咱們來看一個簡單的案例。
查詢代碼以下:git

SqlSession sqlSession = null;
        try {
            sqlSession = DBUtils.openSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            //查詢同一條數據時會緩存
            User user = mapper.getUser(1l);
            User user2 = mapper.getUser(1l);
            System.out.println(user.toString());
            System.out.println(user2.toString());
            sqlSession.commit();
        } catch (Exception e) {
            System.err.println(e.getMessage());
            sqlSession.rollback();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }

咱們來看看日誌:
這裏寫圖片描述
小夥伴們看到,我這裏執行了兩次查詢,但實際上只執行了一次SQL語句。github

本身配置二級緩存

上面的緩存是由系統默認配置的,這個有必定的侷限性,就是隻能在同一個SqlSession中有效,脫離了同一個SqlSession就無法使用這個緩存了,有的時候咱們可能但願可以跨SqlSession進行數據緩存。那麼這個時候須要咱們進行手動開啓二級緩存。
二級緩存的開啓方式其實很簡單,只須要咱們在userMapper.xml中配置<cache/>節點便可。以下:算法

<?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="org.sang.db.UserMapper">
    <cache/>
    <select id="getUser" resultType="org.sang.bean.User" parameterType="Long">
        select * from user where id = #{id}
    </select>
    <insert id="insertUser" parameterType="org.sang.bean.User">
        INSERT INTO user(username,password,address) VALUES (#{username},#{password},#{address})
    </insert>
    <delete id="deleteUser" parameterType="Long">
        DELETE FROM user where id=#{id}
    </delete>
    <select id="getAll" resultType="u">
        SELECT * from user
    </select>
</mapper>

這樣簡單配置以後,二級緩存就算開啓了,這樣的配置中,許多東西都是默認的,好比全部的select語句都會被緩存,全部的delete、insert和update則都會將緩存刷新,還好比緩存將使用LRU算法進行內存回收等。那麼這些東西若是須要配置的話,咱們能夠按以下方式進行配置:
<cache eviction="LRU" flushInterval="20000" size="1024" readOnly="true"/>,這裏的eviction表示緩存策略,除了LRU以外還有先進先出(FIFO)、軟引用(SOFT)、弱引用(WEAK)等,flushInterval則表示刷新時間,表示緩存的對象個數,readOnly爲true則表示緩存只能夠讀取不能夠修改。
OK,作了如上配置以後還不夠,開啓二級緩存還要求咱們的實體類能夠序列化,實現Serializable接口便可,以下:sql

public class User implements Serializable{
    private Long id;
    private String username;
    private String password;
    private String address;

    ...

}

如此以後,咱們的二級緩存就算成功開啓了,OK,我麼來測試下:數據庫

SqlSession sqlSession = null;
        SqlSession sqlSession2 = null;
        try {
            sqlSession = DBUtils.openSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.getUser(1l);
            System.out.println(user.toString());
            sqlSession.commit();
            sqlSession2 = DBUtils.openSqlSession();
            UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
            User user2 = mapper2.getUser(1l);
            System.out.println(user2.toString());
            sqlSession2.commit();
        } catch (Exception e) {
            System.err.println(e.getMessage());
            sqlSession.rollback();
            sqlSession2.rollback();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
            if (sqlSession2 != null) {
                sqlSession2.close();
            }
        }

打印日誌以下:
這裏寫圖片描述
OK,小夥伴們看到SQL語句實際上只執行了一次。緩存

OK,以上就是對mybatis中緩存的一個簡單介紹。markdown

本文案例下載:
本文案例GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test27-mybatis8mybatis

參考資料:
《深刻淺出MyBatis 技術原理與實戰》app

相關文章
相關標籤/搜索