網站首頁 編程語言 正文
1:一級緩存要生效,必須滿足以下條件條件
- 必須是相同的會話
- 必須是同一個 mapper,即同一個 namespace
- 必須是相同的 statement,即同一個 mapper 中的同一個方法
- 必須是相同的 SQL 和參數
- 查詢語句中間沒有執行 session.clearCache() 方法
- 查詢語句中間沒有執行 insert/update/delete 方法
2:與 SpringBoot 集成時一級緩存不生效原因
- 因為一級緩存是會話級別的,要生效的話,必須要在同一個 SqlSession 中。但是與 SpringBoot 集成的 MyBatis,默認每次執行 SQL 語句時,都會創建一個新的 SqlSession!所以一級緩存才沒有生效。
- 當調用 mapper 的方法時,最終會執行到 SqlSessionUtils 的 getSqlSession 方法,在這個方法中會嘗試在事務管理器中獲取 SqlSession,如果沒有開啟事務,那么就會 new 一個 DefaultSqlSession。所以說,即便在同一個方法中,通過同一個 mapper 連續調用兩次相同的查詢方法,也不會觸發一級緩存
3:解決與 SpringBoot 集成時一級緩存不生效問題
只要將方法加上 @Transactional 注解開啟事務,那么一級緩存就會生效
4:mybatis為什么要有二級緩存
- 業務系統中存在很多的靜態數據如,字典表、菜單表、權限表等,這些數據的特性是不會輕易修改但又是查詢的熱點數據
- 一級緩存針對的是同一個會話當中相同 SQL,并不適合熱點數據的緩存場景
- 為了解決這個問題引入了二級緩存,它脫離于會話之外,多個會話可以使用相同的緩存、
5:配置啟動mybatis有二級緩存
- 二級緩存需要手動來開啟,MyBatis 默認沒有開啟二級緩存
- 在 yaml 中配置 cache-enabled 為 true
mybatis-plus:
configuration:
cache-enabled: true
- 實體類實現 Serializable 接口和生成SerialVersionUID
public class SysNotification implements Serializable {
private static final long serialVersionUID = 3470806756562029897L;
- 測試當發送兩次 get 請求時(兩個不同的會話),通過日志可以發現第二次查詢使用的是緩存
Cache Hit Ratio [org.jeecg.modules.system.mapper.SysNotificationMapper]: 0.5
生效的條件:
- 當會話提交或關閉之后才會填充二級緩存
- 必須是同一個 mapper,即同一個命名空間
- 必須是相同的 statement,即同一個 mapper 中的同一個方法
- 必須是相同的 SQL 語句和參數
- 如果 readWrite=true(默認就是true),實體對像必須實現 Serializable 接口
失效的條件:
- 只有修改會話提交之后,才會執行清空操作
- 任何一種增刪改操作都會清空整個 namespace 中的緩存
6:為什么 MyBatis 默認不開啟二級緩存?
- 二級緩存雖然能帶來一定的好處,但是有很大的隱藏危害!
- 它的緩存是以 namespace(mapper) 為單位的,不同 namespace 下的操作互不影響。且 insert/update/delete 操作會清空所在 namespace 下的全部緩存
- 假設現在有 ItemMapper 以及 XxxMapper,在 XxxMapper 中做了表關聯查詢,且做了二級緩存。此時在 ItemMapper 中將 item 信息給刪了,由于不同 namespace 下的操作互不影響,XxxMapper 的二級緩存不會變,那之后再次通過 XxxMapper 查詢的數據就不對了,非常危險,來看一個例子:
@Mapper
@Repository
@CacheNamespace
public interface XxxMapper {
@Select("select i.id itemId,i.name itemName,p.amount,p.unit_price unitPrice " +
"from item i JOIN payment p on i.id = p.item_id where i.id = #{id}")
List<PaymentVO> getPaymentVO(Long id);
}
@Autowired
private XxxMapper xxxMapper;
@Test
void test() {
System.out.println("==================== 查詢PaymentVO ====================");
List<PaymentVO> voList = xxxMapper.getPaymentVO(1L);
System.out.println(JSON.toJSONString(voList.get(0)));
System.out.println("==================== 更新item表的name ==================== ");
Item item = itemMapper.selectById(1);
item.setName("java并發編程");
itemMapper.updateById(item);
System.out.println("==================== 重新查詢PaymentVO ==================== ");
List<PaymentVO> voList2 = xxxMapper.getPaymentVO(1L);
System.out.println(JSON.toJSONString(voList2.get(0)));
}
- 上面的代碼,test() 方法中前后兩次調用了 xxxMapper.getPaymentVO 方法,因為沒有加 @Transactional 注解,所以前后兩次查詢,是兩個不同的會話,第一次查詢完后,SqlSession 會自動 commit,所以二級緩存能夠生效;
- 然后在中間進行了 Item 表的更新操作,修改了下名稱;
- 由于 itemMapper 與 xxxMapper 不是同一個命名空間,所以 itemMapper 執行的更新操作不會影響到 xxxMapper 的二級緩存;
再次調用 xxxMapper.getPaymentVO,發現取出的值是走緩存的,itemName 還是老的。但實際上 itemName 在上面已經被改了! - 所以說,二級緩存的隱藏危害是比較大的,當有表關聯時,一個不注意就會出問題,不建議使用
7:可以使用Spring緩存注解@Cacheable、@CacheEvict、@CachePut
原文鏈接:https://blog.csdn.net/qq_19891197/article/details/131460812
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-04-16 Android給通知channel靜音的方法實例_Android
- 2022-05-18 Python?pandas?計算每行的增長率與累計增長率_python
- 2022-10-17 C#使用WebSocket與網頁實時通信的實現示例_C#教程
- 2022-12-23 C++?Boost?Exception超詳細講解_C 語言
- 2022-05-09 PyTorch手寫數字數據集進行多分類_python
- 2022-07-29 Ceph分布式存儲集群Pool資源池簡介及使用小結_其它綜合
- 2021-12-19 Redis中緩存穿透/擊穿/雪崩問題和解決方法_Redis
- 2022-06-09 FreeRTOS實時操作系統空閑任務的阻塞延時實現_操作系統
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支