MyBatis-22MyBatis缓存配置【一级缓存】
文章目錄
- 概述
- 一級緩存
概述
使用緩存可以使應用更快的獲取數據,避免頻繁的數據庫交互,尤其是在查詢越多、緩存命中率越高的情況下,使用緩存的作用就越明顯。
MyBatis作為持久化框架,提供了非常強大的查詢緩存特性,可以非常方便的配置和定制使用。
一般提到MyBatis的緩存,都是指二級緩存。 一級緩存(也叫本地緩存)默認會啟用,并且不能控制,因此很少提到, 這里僅僅是介紹下一級緩存,了解一級緩存可以避免產生一些難以發現的錯誤。 作為了解即可。
一級緩存
話不多少,直接上代碼演示一級緩存如何起作用的
package com.artisan.mybatis.xml.mapper;import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test;import com.artisan.mybatis.xml.domain.SysUser;/*** * * @ClassName: CacheL1Test* * @Description: 一級緩存設置* * @author: Mr.Yang* * @date: 2018年5月3日 上午12:06:05*/ public class CacheL1Test extends BaseMapperTest {@Testpublic void cacheL1Test() {// 獲取SqlSessionSqlSession sqlSession = getSqlSession();SysUser sysUser1 = null;try {// 獲取UserMapper接口UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 調用接口方法,查詢sysUsersysUser1 = userMapper.selectSysUserById(1L);// 對當前獲取的對象重新賦值sysUser1.setUserName("New Name");System.out.println("再次查詢id相同的sysUser Begin");// 再次查詢id相同的sysUser,確保和上個查詢 方法和參數相同SysUser sysUser2 = userMapper.selectSysUserById(1L);System.out.println("再次查詢id相同的sysUser End");// 雖然么有更新數據庫,但是這個用戶名和sysUser1重新賦值的名字相同Assert.assertEquals("New Name", sysUser2.getUserName());// 無論如何,sysUser1 和 sysUser2 完全就是同一個實例Assert.assertEquals(sysUser1, sysUser2);} finally {// 關閉SqlSessionsqlSession.clearCache();}System.out.println("【---------------開啟新的SqlSession---------------】");// 獲取一個新的SqlSessionsqlSession = getSqlSession();try {// 獲取UserMapper接口UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 調用接口方法,查詢sysUserSysUser sysUser3 = userMapper.selectSysUserById(1L);// 第二個sqlSession獲取的用戶仍然是adminAssert.assertNotEquals("New Name", sysUser3.getUserName());// 這里的sysUser3 和 第一個sqlSession中的sysUser1是兩個不同的實例Assert.assertNotEquals(sysUser1, sysUser3);// 執行刪除操作userMapper.deleteSysUserById(2L);System.out.println("執行刪除操作后,再次查詢id相同的sysUser Begin");// 獲取 sysUser4 ,確保和上個查詢 方法和參數相同SysUser sysUser4 = userMapper.selectSysUserById(1L);System.out.println("執行刪除操作后,再次查詢id相同的sysUser End");// 這里sysUser3和sysUser4是兩個不同的實例Assert.assertNotEquals(sysUser3, sysUser4);} finally {// 關閉SqlSessionsqlSession.clearCache();}} }結合日志一起分析下
2018-05-03 01:12:18,933 INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully 2018-05-03 01:12:18,937 INFO [main] (BaseMapperTest.java:29) - reader close successfully 2018-05-03 01:12:19,075 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Preparing: select a.id, a.user_name, a.user_password, a.user_email, a.user_info, a.head_img, a.create_time from sys_user a where id = ? 2018-05-03 01:12:19,253 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1(Long) 2018-05-03 01:12:19,316 TRACE [main] (BaseJdbcLogger.java:151) - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time 2018-05-03 01:12:19,317 TRACE [main] (BaseJdbcLogger.java:151) - <== Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0 2018-05-03 01:12:19,325 DEBUG [main] (BaseJdbcLogger.java:145) - <== Total: 1 再次查詢id相同的sysUser Begin 再次查詢id相同的sysUser End 【---------------開啟新的SqlSession---------------】 2018-05-03 01:12:19,343 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Preparing: select a.id, a.user_name, a.user_password, a.user_email, a.user_info, a.head_img, a.create_time from sys_user a where id = ? 2018-05-03 01:12:19,344 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1(Long) 2018-05-03 01:12:19,347 TRACE [main] (BaseJdbcLogger.java:151) - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time 2018-05-03 01:12:19,348 TRACE [main] (BaseJdbcLogger.java:151) - <== Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0 2018-05-03 01:12:19,352 DEBUG [main] (BaseJdbcLogger.java:145) - <== Total: 1 2018-05-03 01:12:19,353 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Preparing: delete from sys_user where id = ? 2018-05-03 01:12:19,354 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 2(Long) 2018-05-03 01:12:19,356 DEBUG [main] (BaseJdbcLogger.java:145) - <== Updates: 0 執行刪除操作后,再次查詢id相同的sysUser Begin 2018-05-03 01:12:19,357 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Preparing: select a.id, a.user_name, a.user_password, a.user_email, a.user_info, a.head_img, a.create_time from sys_user a where id = ? 2018-05-03 01:12:19,362 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1(Long) 2018-05-03 01:12:19,364 TRACE [main] (BaseJdbcLogger.java:151) - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time 2018-05-03 01:12:19,365 TRACE [main] (BaseJdbcLogger.java:151) - <== Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0 2018-05-03 01:12:19,368 DEBUG [main] (BaseJdbcLogger.java:145) - <== Total: 1 執行刪除操作后,再次查詢id相同的sysUser End可以看到在第一個sqlSession中,第一次執行selectSysUserById獲取SysUser數據的時候,到數據庫里執行了SQL獲取sysUser1。 第二次獲取sysUser2的時候,從日志來看
再次查詢id相同的sysUser Begin 再次查詢id相同的sysUser End中間并沒有任何到數據庫查詢用戶的操作。
從測試的代碼看,獲取sysUser1后重新設置了userName,之后沒有進行任何更新數據庫的操作。 在獲取susUser2對象后,發現sysUser2對象的userName的值竟然和sysUse1重新設置后的值一樣,再往下繼續看,原來sysUser1和sysUse2竟然是同一個對象,之所以是這樣就是因為MyBatis的一級緩存。
MyBatis的一級緩存存在于SqlSession的生命周期中,在同一個sqlSession中查詢時,MyBatis會把執行的方法和參數通過算法生成緩存的鍵值,將鍵值和查詢結果一起放入Map對象中。 如果同一個SqlSession中執行的方法和參數完全一致,那么通過算法會生成相同的鍵值。 當Map緩存對象中已經存在該鍵值時,則會返回緩存中的對象。
緩存中的對象和我們得到的結果是同一個對象那個,反復使用相同參數執行同一個方法時,總是返回同一個對象。
如果不想讓selectSysUserById使用一級緩存,可以做如下調整
<select id="selectSysUserById" flushCache="true" resultMap="userMap">selecta.id,a.user_name,a.user_password,a.user_email,a.user_info,a.head_img,a.create_timefromsys_user awhere id = #{id}</select>flushCache="true"后,每次在查詢數據前都會清空當前的以及緩存,因此該方法每次都會從數據庫中查詢,此時sysUser1, sysUser2就是兩個不同的實例了。 要避免這樣使用,會增加數據庫的負擔。
在關閉第一個SqlSession后了重新獲取了一個SqlSession,因此有重新查詢了sysUser3,這時日志中輸出了數據庫的查詢SQL,sysUser3是一個新的實例,和 sysUser1沒有任何關系。 因為一級緩存是和SqlSession綁定的,只存在與SqlSession的生命周期中。
接下來執行deleteSysUserById操作,然后使用相同的方法和參數獲取了sysUser4。從日志和結果看,sysUser3和sysUser4是完全不同的兩個對象。 因為任何的insert update delete 操作都會清空一級緩存,所以查詢sysUser4時由于緩存不存在,就會再次之星數據庫的查詢操作。
關于一級緩存的跟蹤情況,通過上面的示例介紹完了,由于一級緩存是在默默的工作,因此要避免在使用過程中由于不了解而發生察覺不到的錯誤。
總結
以上是生活随笔為你收集整理的MyBatis-22MyBatis缓存配置【一级缓存】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MyBatis-21MyBatis高级结
- 下一篇: MyBatis-23MyBatis缓存配