Mybatis緩存的那些事

今天寫代碼的時候碰到了一個情況 簡單的的寫了一個小demo

@Test
    @Transactional
    public void test(){
        Role role = new Role();
        role.setRolename("xxxx");
        int insert = roleMapper.insert(role);
        System.out.println(insert);
        Role roleBase = roleMapper.selectByPrimaryKey(role.getId());
        System.out.println(roleBase);
        change(roleBase.getId(),"aaaa");
        change(roleBase.getId(),"bbbb");
        System.out.println(JSONUtils.toJSONString(roleBase));


    }

    private void change(Integer roleId, String s){
        Role role = roleMapper.selectByPrimaryKey(roleId);
        System.out.println(role);
        role.setRolename(s);
    }

對插入數據庫的一條數據做了一個change操作,但是並沒有傳入roleBase這個對象。

輸出:

通過觀察輸出,可以看出通過 selectByPrimaryKey 這個方法查出的對象是同一個對象,而且roleBase的值被改變了。

第一反應就是用了緩存。

之後通過修改mybatis的配置

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

不啓用緩存,但是查出來的數據依然是一樣的,還是同一個對象。

之後通過對selectByPrimaryKey打斷點,跟蹤執行的流程

這裏將數據緩存進了localCache!!!

 

在網上找了一些cache相關的文章

local cache和cache

mybatis提供了兩種cache類型:local cache和cache

要特別注意的是,mybatis的local cache是無法關閉的。

那麼local cache幹了什麼?在默認配置情況下,mybatis會將同一session內的查詢結果都放在local cache中,這樣可以提高性能,避免每次都hit到數據庫。

那麼cache幹了什麼呢?和local cache相對的,cache是跨session的,也就是說這個session中緩存的結果,在另外一個session中也能夠用到。

 

問題分析

前面已經講到了在同一session中的查詢會將結果緩存,那麼這個和我們一開始提到的問題有什麼關係呢?聰明的你一定已經想到了,這個問題和啓用了事務有關。

實際上mybatis在和spring集成後,會自動將session綁定到事務上,那麼就會產生前面提到的問題。

 

解決辦法

有以下幾種解決辦法:

  1. 在mybatis配置文件中localCacheScope=STATEMENT

  2. 在mapper配置文件中,給select設置flushCache=true。需要注意的是,這樣會將local cache和cache都清空掉。

  3. 不用事務

緩存參考:https://segmentfault.com/a/1190000008207977

 

測試了1,3兩個方法可以結局localcache的問題。2應該也ok

 

學習可以學習美團點評對Mybatis的緩存介紹,講的很詳細了。

https://tech.meituan.com/mybatis_cache.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章