日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

使用Redis做Mybatis的二级缓存

發(fā)布時(shí)間:2024/1/18 数据库 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Redis做Mybatis的二级缓存 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 前言
  • 一、二級(jí)緩存
  • 二、使用步驟
    • 1.開(kāi)啟二級(jí)緩存
    • 2.編寫(xiě)ApplicationContextHolder
    • 3.編寫(xiě)RedisCache二級(jí)緩存工具類
    • 4.在mapper.xml文件中開(kāi)啟全局二級(jí)緩存
    • 5.配置RedisTemplate序列化工具類,實(shí)體也需要實(shí)現(xiàn)序列化接口
  • 三、測(cè)試
  • 總結(jié)


前言

本篇記錄怎么使用Redis做Mybtais的緩存。


一、二級(jí)緩存

MyBatis中的緩存分為一級(jí)緩存和二級(jí)緩存

  • 一級(jí)緩存:基于sqlSession的緩存
  • 二級(jí)緩存:基于多個(gè)sqlSession 共享的namspace數(shù)據(jù)塊

通常一個(gè)mapper 都一個(gè)namespace,所有的相關(guān)二級(jí)緩存都存在該namespace 數(shù)據(jù)塊下
查詢順序:先去二級(jí)緩存,如果二級(jí)沒(méi)有再去一級(jí)緩存,一級(jí)沒(méi)有再去數(shù)據(jù)庫(kù)
注意:在spring 配置的mybatis 中不存在一級(jí)緩存,二級(jí)緩存發(fā)生增刪改,該namespace 下所有緩存數(shù)據(jù) 立即清空,目的是為了避免有臟數(shù)據(jù)存在

二、使用步驟

創(chuàng)建項(xiàng)目,導(dǎo)入依賴和基本編碼部分不再贅述

1.開(kāi)啟二級(jí)緩存

在配置文件yml中加入以下配置

代碼如下:

cache-enabled: true #使用緩存

2.編寫(xiě)ApplicationContextHolder

該類主要是為了在spring環(huán)境中獲取非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中,只要實(shí)現(xiàn)或者繼承xxAware接口或者類,在實(shí)例該對(duì)象時(shí),* 會(huì)調(diào)用實(shí)現(xiàn)xxAware接口的類的方法,把參數(shù)傳遞*/ /*** --效率,是成功的核心關(guān)鍵--* 在spring中獲取非spring管理的bean對(duì)象* @Author lzl* @Date 2023/3/9 08:00*/ @Component public class ApplicationContextHolder implements ApplicationContextAware {//spring容器private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {ApplicationContextHolder.applicationContext = applicationContext;}public static RedisTemplate getRedisTemplate(){return ApplicationContextHolder.applicationContext.getBean("redisTemplate",RedisTemplate.class);} }

3.編寫(xiě)RedisCache二級(jí)緩存工具類

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;/*** 數(shù)據(jù)查詢順序:二級(jí)緩存 -> 一級(jí)緩存 -> 數(shù)據(jù)庫(kù)* 我們?cè)趍ybatis中指定了二級(jí)緩存,在mybatis啟動(dòng)會(huì)生成Cache對(duì)象,* 如果在該類使用@Autowired注入RedisTemplate是無(wú)法注入的,需要使用spring注入*/ /*** --效率,是成功的核心關(guān)鍵--** @Author lzl* @Date 2023/3/9 08:02*/public class RedisCache implements Cache{//RedisTemplate對(duì)象private RedisTemplate redisTemplate;//id相當(dāng)于當(dāng)前sql對(duì)應(yīng)的cache的命名空間 namespace="com.qf.mapper.xxxMapper"private String id;//讀寫(xiě)鎖:多線程中可以共享鎖,如果大家都是讀操作,提高數(shù)據(jù)的讀的并發(fā)能力//如果有一個(gè)人進(jìn)行了寫(xiě)操作,其他人都不能進(jìn)行讀寫(xiě)操作了private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();//獲取RedisTemplate對(duì)象public RedisTemplate getRedisTemplate(){//判斷if(redisTemplate == null){synchronized (RedisCache.class){if(redisTemplate == null){RedisTemplate redisTemplate = ApplicationContextHolder.getRedisTemplate();//設(shè)置key使用string類型的序列化方式redisTemplate.setKeySerializer(RedisSerializer.string());return redisTemplate;}return this.redisTemplate;}}return redisTemplate;}@Overridepublic ReadWriteLock getReadWriteLock() {return readWriteLock;}//構(gòu)造器public RedisCache(String id) {System.out.println("id:"+id);this.id = id;}//id相當(dāng)于當(dāng)前sql對(duì)應(yīng)的cache的命名空間@Overridepublic String getId() {System.out.println("getId:"+id);return id;}/*** 將結(jié)果放入緩存,當(dāng)訪問(wèn)查詢方法時(shí)調(diào)用,所以這里必須通過(guò)getRedisTemplate()方法來(lái)獲取redisTemplate對(duì)象* @param key -> 命名空間 + sql + 參數(shù) = 組成的字符串* @param value -> sql查詢的結(jié)果*/@Overridepublic void putObject(Object key, Object value) {System.out.println("putObject中的key:"+key);System.out.println("putObject中的value:"+value);getRedisTemplate().opsForValue().set(key.toString(),value);}/*** 獲取緩存中的數(shù)據(jù),當(dāng)訪問(wèn)查詢方法時(shí)調(diào)用,所以這里必須通過(guò)getRedisTemplate()方法來(lái)獲取redisTemplate對(duì)象* @param key* @return*/@Overridepublic Object getObject(Object key) {System.out.println("getObject:"+key);return getRedisTemplate().opsForValue().get(key.toString());}/*** 從緩存中移除數(shù)據(jù),當(dāng)訪問(wèn)查詢方法時(shí)調(diào)用,所以這里必須通過(guò)getRedisTemplate()方法來(lái)獲取redisTemplate對(duì)象* @param key* @return*/@Overridepublic Object removeObject(Object key) {System.out.println("removeObject:"+key);return getRedisTemplate().delete(key.toString());}/*** 清空緩存*/@Overridepublic void clear() {System.out.println("clear");Set keys = getRedisTemplate().keys("*" + id + "*");System.out.println("清空緩存keys:"+keys);getRedisTemplate().delete(keys);}/*** 獲取緩存數(shù)據(jù)長(zhǎng)度* @return*/@Overridepublic int getSize() {Set keys = getRedisTemplate().keys("*" + id + "*");return keys.size();}}

4.在mapper.xml文件中開(kāi)啟全局二級(jí)緩存

<!-- 開(kāi)啟二級(jí)緩存(全局) --><!--type:使用自定義的對(duì)象進(jìn)行存儲(chǔ)blocking:true 查詢時(shí)是否阻塞加鎖flushInterval: 毫秒值,緩存多久清空一次eviction: 緩存失效策略: LRU – 最近最少使用:移除最長(zhǎng)時(shí)間不被使用的對(duì)象。FIFO – 先進(jìn)先出:按對(duì)象進(jìn)入緩存的順序來(lái)移除它們。SOFT – 軟引用:基于垃圾回收器狀態(tài)和軟引用規(guī)則移除對(duì)象。WEAK – 弱引用:更積極地基于垃圾收集器狀態(tài)和弱引用規(guī)則移除對(duì)象。readOnly:true 只讀,不能被修改size: 1024 緩存的大小--><cache type="com.lzl.secondcache.RedisCache"/>

5.配置RedisTemplate序列化工具類,實(shí)體也需要實(shí)現(xiàn)序列化接口

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; /*** --效率,是成功的核心關(guān)鍵--** @Author lzl* @Date 2023/3/9 08:05*/ @Configuration public class RedisConfig {/*** springboot 默認(rèn)幫我們創(chuàng)建的RedisTemplate的key和value的序列化方式是jdk默認(rèn)的方式,* 我們有時(shí)候手動(dòng)向redis中添加的數(shù)據(jù)可能無(wú)法被查詢解析出來(lái),所以我們需要修改序列化方式* @param connectionFactory* @return*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();// 配置連接工廠redisTemplate.setConnectionFactory(connectionFactory);// 使用StringRedisSerializer來(lái)序列化和反序列化Redis的key值StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// 使用Jackson2JsonRedisSerializer來(lái)序列化和反序列化Redis的value值Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);// 配置對(duì)象映射器ObjectMapper objectMapper = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修飾符范圍。ANY指包括private和public修飾符范圍objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化輸入類型,類的信息也將添加到j(luò)son中,這樣才可以根據(jù)類名反序列化。objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);// 將對(duì)象映射器添加到序列化器中jackson2JsonRedisSerializer.setObjectMapper(objectMapper);// 配置key,value,hashKey,hashValue的序列化方式redisTemplate.setKeySerializer(stringRedisSerializer);redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.setHashKeySerializer(stringRedisSerializer);redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);return redisTemplate;} }

需要注意的是參數(shù)列表會(huì)報(bào)一個(gè)無(wú)法自動(dòng)注入的錯(cuò)誤,屬于正常現(xiàn)象,不影響代碼正常運(yùn)行

實(shí)體類需要實(shí)現(xiàn)序列化接口如下圖所示

三、測(cè)試

首先我們先開(kāi)啟Redis,這里開(kāi)虛擬機(jī)太麻煩,我使用了windows版的redis



啟動(dòng)成功

啟動(dòng)項(xiàng)目

啟動(dòng)成功,測(cè)試二級(jí)緩存的基本思路是,先調(diào)用查詢的方法,查看redis中是否有緩存數(shù)據(jù),再調(diào)用刪除的方法,再次查看查看redis中的緩存數(shù)據(jù)是否被刪除

先執(zhí)行查詢

查看控制臺(tái)

我這里之前已經(jīng)查過(guò)一次,所以直接調(diào)用了緩存,沒(méi)有執(zhí)行sql語(yǔ)句,如果是第一次訪問(wèn),會(huì)先執(zhí)行sql語(yǔ)句,再建立緩存
執(zhí)行刪除

查看控制臺(tái)

刪除成功!我們?cè)俅螆?zhí)行查詢


查看控制臺(tái):

發(fā)現(xiàn)執(zhí)行了sql語(yǔ)句
再次查詢

緩存命中!大功告成!


總結(jié)

本篇簡(jiǎn)單記錄一下springboot整合mybatis使用redis做二級(jí)緩存

總結(jié)

以上是生活随笔為你收集整理的使用Redis做Mybatis的二级缓存的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。