mybaties的緩存(轉)
前言
本篇意在通過Hibernate和Mybaitis緩存,通過對比學習,同時弄懂這兩者中的區別
Hibernate中的緩存
Hibernate中一般常用的緩存有三個,一級緩存
,二級緩存
,查詢緩存
,要了解一二級緩存的可以點擊->圖解SSH-Hibernate,這裏主要講解一下二級緩存和查詢緩存
首先我們先看一下Hibernate的二級緩存
Hibernate二級緩存.png
文字描述過程:
-
首先我們
get(1L)
的時候,由於二級緩存中沒有,所以我們就去數據庫查詢,並將結果返回後插入到二級緩存中,然後將結果插入到二級緩存中,並將數據返回. -
當我們再次查詢時,由於
二級緩存
那麽我們再來看看Hibernate中的查詢緩存
Hibernate查詢緩存.png
文字描述過程:
-
首先
list()
的時候,由於查詢緩存中沒有,那麽我們去數據庫查,並將數據放在了查詢緩存中,然後將結果返回 -
當我們進行
insert
操作的時候,首先會給數據庫增加一條數據,然後關鍵的地方來了,此時Hibernate會清空所有的查詢緩存,因為此時數據庫中的數據已經變了,如果不清空緩存,就會導致select * from User
拿到的還是1L和2L,但是此時正確的應該是1L,2L,3L,所以必須清空 -
然後我們再次
list()
從以上過程我們就可以看出,Hibernate的查詢緩存的命中率的非常低的,進行新增、編輯、刪除操作都會去清空查詢緩存,所以一般不使用查詢緩存,而是使用二級緩存.
Mybaitis中的緩存
一般我們都不說MyBatis的二級緩存,而是說MyBatis的緩存,我們先來看代碼
@Test
public void testCache() throws Exception {
SqlSession session = MybatisUtil.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User u1 = userMapper.get(1L);
session.close();
session = MybatisUtil.openSession();
userMapper = session.getMapper(UserMapper.class);
User u2 = userMapper.get(1L);
session.close();
}
這段代碼中, Mybatis一共發了兩條SQL,這就好像說, Mybatis中沒有二級緩存
,然後我們打開Mybatis的文檔一看,頓時震驚
Mybatis文檔.png
這難道是騙人的,說好的默認開啟緩存呢.....
其實不是的,默認確實是開啟緩存的,但是我們還需要配置一點東西
UserMapper.xml
<mapper namespace="com.toby.mybatis.domain.UserMapper">
<!--mybatis中默認是支持二級緩存的,
要是某個對象由二級緩存,需要在mapper.xml中配置如下標簽-->
<cache/>
...
</mapper>
另外,對象還要實現序列化接口,否則報NotSerializableException
的異常
public class User implements Serializable{
...
}
設置完畢之後,我們再來嘗試insert
的問題
@Test
public void testCache() throws Exception {
SqlSession session = MybatisUtil.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User u1 = userMapper.get(1L);
session.close();
//insert
session = MybatisUtil.openSession();
userMapper = session.getMapper(UserMapper.class);
User user = new User();
userMapper.add(user);
session.commit();
session.close();
session = MybatisUtil.openSession();
userMapper = session.getMapper(UserMapper.class);
User u2 = userMapper.get(1L);
session.close();
}
此時發現,發了3條SQL,那麽究竟是什麽原因呢?
首先,get
的底層用的是selectOne
,然後selectOne
又用的是用selectList
,所以Mybatis是沒有二級緩存的概念,他的緩存,全都是查詢緩存.此時如下圖
Mybatis緩存.png
看完這個圖,就明白為什麽get(1L)->add()->get(1L)
這個過程會發3條SQL了,因為insert
的時候,清空了緩存
但是就算insert
,並沒有影響到get(1L)
的結果,但是你卻把他的緩存也清空了,這明顯不合理,那麽我們怎麽樣讓Mybatis中的緩存更像Hibernate中的二級緩存
呢?因為目前這樣的緩存實在太坑,從這過程大家應該感受得到.
那麽我們可不可以這樣做呢?如圖:
mybatis緩存改進.png
也就是我們做了兩件事
-
list
由於緩存命中率低,那麽我們就不加入到緩存中 -
insert
我們不清空緩存
這樣做,Mybatis的緩存就顯得更像Hibernate中的二級緩存了,那麽在代碼中,我們具體是怎麽實現的呢?
UserMapper.xml
<!--useCache默認是true,這裏我們設置為false就是讓他不使用緩存-->
<select id="list" resultType="com.toby.mybatis.domain.User" useCache="false">
SELECT * FROM user
</select>
<!--flushCache默認為true,我們設置為false,就是讓他不清空緩存-->
<insert id="add" parameterType="com.toby.mybatis.domain.User"
useGeneratedKeys="true" keyProperty="id" keyColumn="id"
flushCache="false">
INSERT INTO USER (username) VALUES (#{username})
</insert>
這樣之後,我們Mybatis中的緩存就更高效了
mybaties的緩存(轉)