Mybatis 一級快取和引發的問題
1.Mybatis 是預設開啟一級快取的。跟Spring結合使用的話執行的方法必須開啟事務一級快取才有效。
2.當查詢資料時候,先從快取中尋找是否存在該條資料,存在就直接取出來,不存在,向資料庫傳送sql查詢, 然後將查詢後的資料存入快取返回給程式。
下邊圍繞著如下幾個問題展開驗證:
- 開啟事務,一級快取有效
- 不開啟事務,一級快取失效
- Mybatis一級快取的坑在哪呢?
- 驗證一個事物中進行insert update delete 會重新整理一級快取
二 驗證
1.開啟事務,一級快取有效。從日誌看到確實只執行了一次查詢。
@Test
@Transactional
public void test() {
LangUser langUser = langUserMapper.selectByPrimaryKey(-1);
LangUser langUser1 = langUserMapper.selectByPrimaryKey(-1);
LangUser langUser2 = langUserMapper.selectByPrimaryKey(-1);
}
15:58:20.584 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
15:58:20.594 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@63648ee9]
15:58:21.095 [main] WARN com.alibaba.druid.pool.DruidDataSource - removeAbandoned is true, not use in productiion.
15:58:21.872 [main] INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited
15:58:21.899 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@4351171a] will be managed by Spring
15:58:21.902 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ?
15:58:21.974 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
15:58:22.013 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Columns: ID, NAME, AGE, SCORE
15:58:22.020 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Row: -1, 小狼, 18, 100
15:58:22.022 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Total: 1
15:58:22.024 [main] DEBUG com.alibaba.druid.pool.PreparedStatementPool - {conn-10004, pstmt-20000} enter cache
2.不開啟事務,一級快取失效
@Test
public void test() {
LangUser langUser = langUserMapper.selectByPrimaryKey(-1);
LangUser langUser1 = langUserMapper.selectByPrimaryKey(-1);
LangUser langUser2 = langUserMapper.selectByPrimaryKey(-1);
}
注意看日誌列印,下面這句話執行了出現了三次,每一次查詢都建立了一個sqlSeesion,sql也執行了三次。
16:02:29.606 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:02:29.606 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:02:29.612 [main] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4c6daf0] was not registered for synchronization because synchronization is not active
16:02:29.863 [main] WARN com.alibaba.druid.pool.DruidDataSource - removeAbandoned is true, not use in productiion.
16:02:31.175 [main] INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited
16:02:31.224 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3088660d] will not be managed by Spring
16:02:31.230 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ?
16:02:31.335 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
16:02:31.397 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Columns: ID, NAME, AGE, SCORE
16:02:31.409 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Row: -1, 小狼, 18, 100
16:02:31.413 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Total: 1
16:02:31.414 [main] DEBUG com.alibaba.druid.pool.PreparedStatementPool - {conn-10004, pstmt-20000} enter cache
16:02:31.417 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4c6daf0]
16:02:31.420 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:02:31.422 [main] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@272a179c] was not registered for synchronization because synchronization is not active
16:02:31.423 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3088660d] will not be managed by Spring
16:02:31.425 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ?
16:02:31.426 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
16:02:31.430 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Columns: ID, NAME, AGE, SCORE
16:02:31.430 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Row: -1, 小狼, 18, 100
16:02:31.431 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Total: 1
16:02:31.435 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@272a179c]
16:02:31.435 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:02:31.437 [main] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67207d8a] was not registered for synchronization because synchronization is not active
16:02:31.438 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3088660d] will not be managed by Spring
16:02:31.439 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ?
16:02:31.442 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
16:02:31.444 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Columns: ID, NAME, AGE, SCORE
16:02:31.444 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Row: -1, 小狼, 18, 100
16:02:31.444 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Total: 1
16:02:31.445 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67207d8a]
16:02:31.480 [Thread-1] INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-0} closing ...
16:02:31.484 [Thread-1] INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} closing ...
16:02:31.589 [Thread-1] INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} closed
3.坑在哪呢?我們看這種開啟事務的情況。
第一次查詢後,我只是把查詢出來的物件賦值“喜洋洋”,我並沒有跟資料庫有任何互動,下面的兩次查詢結果竟然修改後的“喜洋洋”。
@Test
@Transactional
public void test() {
LangUser langUser = langUserMapper.selectByPrimaryKey(-1);
logger.info("姓名:"+langUser.getName());
langUser.setName("喜洋洋");
LangUser langUser1 = langUserMapper.selectByPrimaryKey(-1);
logger.info("姓名:"+langUser1.getName());
LangUser langUser2 = langUserMapper.selectByPrimaryKey(-1);
logger.info("姓名:"+langUser2.getName());
}
16:16:22.983 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:16:22.991 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@117e0fe5]
16:16:23.437 [main] WARN com.alibaba.druid.pool.DruidDataSource - removeAbandoned is true, not use in productiion.
16:16:24.423 [main] INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited
16:16:24.459 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3c2772d1] will be managed by Spring
16:16:24.463 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ?
16:16:24.575 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
16:16:24.604 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Columns: ID, NAME, AGE, SCORE
16:16:24.612 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Row: -1, 小狼, 18, 100
16:16:24.615 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <== Total: 1
16:16:24.617 [main] DEBUG com.alibaba.druid.pool.PreparedStatementPool - {conn-10004, pstmt-20000} enter cache
16:16:24.618 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@117e0fe5]
16:16:24.618 [main] INFO com.hao.xu.lang.mapper.oracle.LangUserMapperTest - 姓名:小狼
16:16:24.620 [main] INFO com.hao.xu.lang.mapper.oracle.LangUserMapperTest - 姓名:喜洋洋
16:16:24.621 [main] INFO com.hao.xu.lang.mapper.oracle.LangUserMapperTest - 姓名:喜洋洋
16:16:24.622 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@117e0fe5]
16:16:24.623 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@117e0fe5]
原因:
當資料庫建立一次連線,就會建立一個SqlSession物件,預設是DefaultSqlSession這個實現,這個物件給使用者提供了運算元據庫的各種方法,與此同時,也會建立一個Executor執行器,快取資訊就是維護在Executor中,如果這個sqlSessio進行
insert update delete 它會釋放掉Executor中的快取
4.驗證一個事物中進行insert update delete 會重新整理一級快取
@Test
@Transactional
public void test() {
LangUser langUser = langUserMapper.selectByPrimaryKey(-1);
logger.info("姓名:"+langUser.getName());
langUser.setName("喜洋洋");
//新建物件插入表中,讓sqlsession 有提交動作
LangUser langUser3 = new LangUser();
langUser3.setName("紅太狼");
langUser3.setAge(5);
langUser3.setScore("90");
langUserMapper.insert(langUser3);
LangUser langUser1 = langUserMapper.selectByPrimaryKey(-1);
logger.info("姓名:"+langUser1.getName());
LangUser langUser2 = langUserMapper.selectByPrimaryKey(-1);
logger.info("姓名:"+langUser2.getName());
}
分析下console 其中有寫日誌我刪除了為了方便大家閱讀:
相關文章
- Mybatis的快取——一級快取和原始碼分析MyBatis快取原始碼
- mybatis二級快取引數MyBatis快取
- MyBatis快取機制(一級快取,二級快取)MyBatis快取
- mybatis原始碼學習:一級快取和二級快取分析MyBatis原始碼快取
- mybatis快取之一級快取(一)MyBatis快取
- Mybatis 一級快取和二級快取原理區別 (圖文詳解)MyBatis快取
- mybatis快取-二級快取MyBatis快取
- mybatis快取之一級快取(二)MyBatis快取
- Mybatis的二級快取MyBatis快取
- 被mybatis一級快取坑了MyBatis快取
- Mybatis的二級快取、使用Redis做二級快取MyBatis快取Redis
- 快取問題(一) 快取穿透、快取雪崩、快取併發 核心概念快取穿透
- Mybatis二級快取使用MyBatis快取
- Mybatis一級快取和結合Spring Framework後失效的原始碼探究MyBatis快取SpringFramework原始碼
- mybatis原始碼詳細解析(2)---- 一級,二級快取MyBatis原始碼快取
- 電腦CPU二級快取的開啟方法和如何檢視二級快取的引數快取
- 快取的問題快取
- 快取問題(四) 快取穿透、快取雪崩、快取併發 解決案例快取穿透
- Mybatis 二級快取應用 (21)MyBatis快取
- Mybatis的快取MyBatis快取
- Mybatis PageHelper編譯SQL引發的一次效能問題.18286262MyBatis編譯SQL
- 程式碼解決快取穿透和快取雪崩問題快取穿透
- Redis快取穿透、快取雪崩、redis併發問題分析Redis快取穿透
- Java後端--32--Mybatis的多級快取和懶載入Java後端MyBatis快取
- 高併發快取面臨的問題快取
- mybatis基礎系列(四)——關聯查詢、延遲載入、一級快取與二級快取MyBatis快取
- Redis 的高效能快取機制的三類問題:快取擊穿、快取雪崩 和 快取穿透Redis快取穿透
- MyBatis 快取MyBatis快取
- MyBatis的快取玩法MyBatis快取
- spring和mybatis中的連線池和快取SpringMyBatis快取
- Mybatis整合二級快取與同時使用快取與事務存在的坑MyBatis快取
- mybatis延遲載入和快取MyBatis快取
- myBatis原始碼解析-二級快取的實現方式MyBatis原始碼快取
- 一次快取效能問題排查快取
- 聊一聊Integer的快取機制問題快取
- 深入理解 MyBatis的二級快取的設計原理MyBatis快取
- SpringBoot 下 Mybatis 的快取Spring BootMyBatis快取
- MyBatis 的快取機制MyBatis快取