網站首頁 編程語言 正文
文章目錄
- 前言
- 一、二級緩存
- 二、使用步驟
- 1.開啟二級緩存
- 2.編寫ApplicationContextHolder
- 3.編寫RedisCache二級緩存工具類
- 4.在mapper.xml文件中開啟全局二級緩存
- 5.配置RedisTemplate序列化工具類,實體也需要實現序列化接口
- 三、測試
- 總結
前言
本篇記錄怎么使用Redis做Mybtais的緩存。
一、二級緩存
MyBatis中的緩存分為一級緩存和二級緩存
- 一級緩存:基于sqlSession的緩存
- 二級緩存:基于多個sqlSession 共享的namspace數據塊
通常一個mapper 都一個namespace,所有的相關二級緩存都存在該namespace 數據塊下
查詢順序:先去二級緩存,如果二級沒有再去一級緩存,一級沒有再去數據庫
注意:在spring 配置的mybatis 中不存在一級緩存,二級緩存發生增刪改,該namespace 下所有緩存數據 立即清空,目的是為了避免有臟數據存在
二、使用步驟
創建項目,導入依賴和基本編碼部分不再贅述
1.開啟二級緩存
在配置文件yml中加入以下配置
代碼如下:
cache-enabled: true #使用緩存
2.編寫ApplicationContextHolder
該類主要是為了在spring環境中獲取非spring容器管理的bean
package com.lzl.secondcache;
import org.springframework.stereotype.Component;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.RedisTemplate;
/**
* 在spring中,只要實現或者繼承xxAware接口或者類,在實例該對象時,
* 會調用實現xxAware接口的類的方法,把參數傳遞
*/
/**
* --效率,是成功的核心關鍵--
* 在spring中獲取非spring管理的bean對象
* @Author lzl
* @Date 2023/3/9 08:00
*/
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
//spring容器
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextHolder.applicationContext = applicationContext;
}
public static RedisTemplate getRedisTemplate(){
return ApplicationContextHolder.applicationContext
.getBean("redisTemplate",RedisTemplate.class);
}
}
3.編寫RedisCache二級緩存工具類
package com.lzl.secondcache;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 數據查詢順序:二級緩存 -> 一級緩存 -> 數據庫
* 我們在mybatis中指定了二級緩存,在mybatis啟動會生成Cache對象,
* 如果在該類使用@Autowired注入RedisTemplate是無法注入的,需要使用spring注入
*/
/**
* --效率,是成功的核心關鍵--
*
* @Author lzl
* @Date 2023/3/9 08:02
*/
public class RedisCache implements Cache{
//RedisTemplate對象
private RedisTemplate redisTemplate;
//id相當于當前sql對應的cache的命名空間 namespace="com.qf.mapper.xxxMapper"
private String id;
//讀寫鎖:多線程中可以共享鎖,如果大家都是讀操作,提高數據的讀的并發能力
//如果有一個人進行了寫操作,其他人都不能進行讀寫操作了
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//獲取RedisTemplate對象
public RedisTemplate getRedisTemplate(){
//判斷
if(redisTemplate == null){
synchronized (RedisCache.class){
if(redisTemplate == null){
RedisTemplate redisTemplate = ApplicationContextHolder.getRedisTemplate();
//設置key使用string類型的序列化方式
redisTemplate.setKeySerializer(RedisSerializer.string());
return redisTemplate;
}
return this.redisTemplate;
}
}
return redisTemplate;
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
//構造器
public RedisCache(String id) {
System.out.println("id:"+id);
this.id = id;
}
//id相當于當前sql對應的cache的命名空間
@Override
public String getId() {
System.out.println("getId:"+id);
return id;
}
/**
* 將結果放入緩存,當訪問查詢方法時調用,所以這里必須通過getRedisTemplate()方法來獲取redisTemplate對象
* @param key -> 命名空間 + sql + 參數 = 組成的字符串
* @param value -> sql查詢的結果
*/
@Override
public void putObject(Object key, Object value) {
System.out.println("putObject中的key:"+key);
System.out.println("putObject中的value:"+value);
getRedisTemplate().opsForValue().set(key.toString(),value);
}
/**
* 獲取緩存中的數據,當訪問查詢方法時調用,所以這里必須通過getRedisTemplate()方法來獲取redisTemplate對象
* @param key
* @return
*/
@Override
public Object getObject(Object key) {
System.out.println("getObject:"+key);
return getRedisTemplate().opsForValue().get(key.toString());
}
/**
* 從緩存中移除數據,當訪問查詢方法時調用,所以這里必須通過getRedisTemplate()方法來獲取redisTemplate對象
* @param key
* @return
*/
@Override
public Object removeObject(Object key) {
System.out.println("removeObject:"+key);
return getRedisTemplate().delete(key.toString());
}
/**
* 清空緩存
*/
@Override
public void clear() {
System.out.println("clear");
Set keys = getRedisTemplate().keys("*" + id + "*");
System.out.println("清空緩存keys:"+keys);
getRedisTemplate().delete(keys);
}
/**
* 獲取緩存數據長度
* @return
*/
@Override
public int getSize() {
Set keys = getRedisTemplate().keys("*" + id + "*");
return keys.size();
}
}
4.在mapper.xml文件中開啟全局二級緩存
<!-- 開啟二級緩存(全局) -->
<!--
type:使用自定義的對象進行存儲
blocking:true 查詢時是否阻塞加鎖
flushInterval: 毫秒值,緩存多久清空一次
eviction: 緩存失效策略: LRU – 最近最少使用:移除最長時間不被使用的對象。
FIFO – 先進先出:按對象進入緩存的順序來移除它們。
SOFT – 軟引用:基于垃圾回收器狀態和軟引用規則移除對象。
WEAK – 弱引用:更積極地基于垃圾收集器狀態和弱引用規則移除對象。
readOnly:true 只讀,不能被修改
size: 1024 緩存的大小
-->
<cache type="com.lzl.secondcache.RedisCache"/>
5.配置RedisTemplate序列化工具類,實體也需要實現序列化接口
package com.lzl.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* --效率,是成功的核心關鍵--
*
* @Author lzl
* @Date 2023/3/9 08:05
*/
@Configuration
public class RedisConfig {
/**
* springboot 默認幫我們創建的RedisTemplate的key和value的序列化方式是jdk默認的方式,
* 我們有時候手動向redis中添加的數據可能無法被查詢解析出來,所以我們需要修改序列化方式
* @param connectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 配置連接工廠
redisTemplate.setConnectionFactory(connectionFactory);
// 使用StringRedisSerializer來序列化和反序列化Redis的key值
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 使用Jackson2JsonRedisSerializer來序列化和反序列化Redis的value值
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
// 配置對象映射器
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修飾符范圍。ANY指包括private和public修飾符范圍
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化輸入類型,類的信息也將添加到json中,這樣才可以根據類名反序列化。
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
// 將對象映射器添加到序列化器中
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 配置key,value,hashKey,hashValue的序列化方式
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
return redisTemplate;
}
}
需要注意的是參數列表會報一個無法自動注入的錯誤,屬于正常現象,不影響代碼正常運行
實體類需要實現序列化接口如下圖所示
三、測試
首先我們先開啟Redis,這里開虛擬機太麻煩,我使用了windows版的redis
啟動成功
啟動項目
啟動成功,測試二級緩存的基本思路是,先調用查詢的方法,查看redis中是否有緩存數據,再調用刪除的方法,再次查看查看redis中的緩存數據是否被刪除
先執行查詢
查看控制臺
我這里之前已經查過一次,所以直接調用了緩存,沒有執行sql語句,如果是第一次訪問,會先執行sql語句,再建立緩存
執行刪除
查看控制臺
刪除成功!我們再次執行查詢
查看控制臺:
發現執行了sql語句
再次查詢
緩存命中!大功告成!
總結
本篇簡單記錄一下springboot整合mybatis使用redis做二級緩存
原文鏈接:https://blog.csdn.net/l_zl2021/article/details/129396623
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-05-12 Natapp(Ngrok) Windows下注冊為服務,開機啟動&后臺運行
- 2022-05-22 asp.net?Core中同名服務注冊的實現代碼_實用技巧
- 2021-12-14 go調用shell命令兩種方式實現(有無返回值)_Golang
- 2022-06-19 C#中的checksum計算公式_C#教程
- 2022-12-01 解決k8s?namespace?一直處于?Terminating?狀態的問題_云其它
- 2022-03-03 關于使用iview table 組件中使用 tooltip 樣式覆蓋的問題
- 2022-05-06 docker?save與docker?export的區別_docker
- 2022-04-30 DataGridView凍結列或行、列順序調整、操作行頭列頭標題的方法_C#教程
- 欄目分類
-
- 最近更新
-
- 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同步修改后的遠程分支