最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis Plus整合Redis實現(xiàn)分布式二級緩存的問題

 更新時間:2023年11月15日 09:43:09   作者:愛碼猿  
Mybatis內(nèi)置的二級緩存在分布式環(huán)境下存在分布式問題,無法使用,但是我們可以整合Redis來實現(xiàn)分布式的二級緩存,這篇文章給大家介紹MyBatis Plus整合Redis實現(xiàn)分布式二級緩存,感興趣的朋友跟隨小編一起看看吧

MyBatis緩存描述

MyBatis提供了兩種級別的緩存, 分別時一級緩存和二級緩存。一級緩存是SqlSession級別的緩存,只在SqlSession對象內(nèi)部存儲緩存數(shù)據(jù),如果SqlSession對象不一樣就無法命中緩存,二級緩存是mapper級別的緩存,只要使用的Mapper類一樣就能夠共享緩存。

在查詢數(shù)據(jù)時,Mybatis會優(yōu)先查詢二級緩存,如果二級緩存沒有則查詢一級緩存,都沒有才會進(jìn)行數(shù)據(jù)庫查詢。

Mybatis的一級緩存默認(rèn)是開啟的,而二級緩存需要在mapper.xml配置文件內(nèi)或通過@CacheNamespace注解手動開啟。

需要注意的是,在于Spring進(jìn)行整合時,必須開啟事務(wù)一級緩存會生效,因為不開啟緩存的話每次查詢都會重新創(chuàng)建一個SqlSession對象,因此無法共享緩存。

通過@CacheNamespace開啟某個Mapper的二級緩存。

@Mapper
@CacheNamespace 
public interface EmployeeMapper extends BaseMapper<Employee> {
}

開啟所有的二級緩存:

mybatis-plus:
    mapper-locations: classpath:mybatis/mapper/*.xml
    configuration:
      cache-enabled: true

MybatisPlus整合Redis實現(xiàn)分布式二級緩存

Mybatis內(nèi)置的二級緩存在分布式環(huán)境下存在分布式問題,無法使用,但是我們可以整合Redis來實現(xiàn)分布式的二級緩存。

1.引入依賴

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.4.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.24.3</version>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.22</version>
</dependency>

2.配置RedisTemplate

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching
public class RedisConfiguration {
    private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer();
    private static final GenericJackson2JsonRedisSerializer JACKSON__SERIALIZER = new GenericJackson2JsonRedisSerializer();
    @Bean
    @Primary
    public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        //設(shè)置緩存過期時間
        RedisCacheConfiguration redisCacheCfg = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(STRING_SERIALIZER))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON__SERIALIZER));
        return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheCfg)
                .build();
    }
    @Bean
    @Primary
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 配置redisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        // key序列化
        redisTemplate.setKeySerializer(STRING_SERIALIZER);
        // value序列化
        redisTemplate.setValueSerializer(JACKSON__SERIALIZER);
        // Hash key序列化
        redisTemplate.setHashKeySerializer(STRING_SERIALIZER);
        // Hash value序列化
        redisTemplate.setHashValueSerializer(JACKSON__SERIALIZER);
        // 設(shè)置支持事務(wù)
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    @Bean
    public RedisSerializer<Object> redisSerializer() {
        //創(chuàng)建JSON序列化器
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //必須設(shè)置,否則無法將JSON轉(zhuǎn)化為對象,會轉(zhuǎn)化成Map類型
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        return new GenericJackson2JsonRedisSerializer(objectMapper);
    }
}

3.自定義緩存類

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
@Slf4j
public class MybatisRedisCache implements Cache {
    // redisson 讀寫鎖
    private final RReadWriteLock redissonReadWriteLock;
    // redisTemplate
    private final RedisTemplate redisTemplate;
    // 緩存Id
    private final String id;
    //過期時間 10分鐘
    private final long expirationTime = 1000*60*10;
    public MybatisRedisCache(String id) {
        this.id = id;
        //獲取redisTemplate
        this.redisTemplate = SpringUtil.getBean(RedisTemplate.class);
        //創(chuàng)建讀寫鎖
        this.redissonReadWriteLock = SpringUtil.getBean(RedissonClient.class).getReadWriteLock("mybatis-cache-lock:"+this.id);
    }
    @Override
    public void putObject(Object key, Object value) {
        //使用redis的Hash類型進(jìn)行存儲
        redisTemplate.opsForValue().set(getCacheKey(key),value,expirationTime, TimeUnit.MILLISECONDS);
    }
    @Override
    public Object getObject(Object key) {
        try {
            //根據(jù)key從redis中獲取數(shù)據(jù)
            Object cacheData = redisTemplate.opsForValue().get(getCacheKey(key));
            log.debug("[Mybatis 二級緩存]查詢緩存,cacheKey={},data={}",getCacheKey(key), JSONUtil.toJsonStr(cacheData));
            return cacheData;
        } catch (Exception e) {
            log.error("緩存出錯",e);
        }
        return null;
    }
    @Override
    public Object removeObject(Object key) {
        if (key != null) {
            log.debug("[Mybatis 二級緩存]刪除緩存,cacheKey={}",getCacheKey(key));
            redisTemplate.delete(key.toString());
        }
        return null;
    }
    @Override
    public void clear() {
        log.debug("[Mybatis 二級緩存]清空緩存,id={}",getCachePrefix());
        Set keys = redisTemplate.keys(getCachePrefix()+":*");
        redisTemplate.delete(keys);
    }
    @Override
    public int getSize() {
        Long size = (Long) redisTemplate.execute((RedisCallback<Long>) RedisServerCommands::dbSize);
        return size.intValue();
    }
    @Override
    public ReadWriteLock getReadWriteLock() {
        return this.redissonReadWriteLock;
    }
    @Override
    public String getId() {
        return this.id;
    }
    public String getCachePrefix(){
        return "mybatis-cache:%s".formatted(this.id);
    }
    private String getCacheKey(Object key){
        return getCachePrefix()+":"+key;
    }
}

4.Mapper接口上開啟二級緩存

//開啟二級緩存并指定緩存類
@CacheNamespace(implementation = MybatisRedisCache.class,eviction = MybatisRedisCache.class)
@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {
}

到此這篇關(guān)于MyBatis Plus整合Redis實現(xiàn)分布式二級緩存的文章就介紹到這了,更多相關(guān)MyBatis Plus整合Redis二級緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot集成mybatis-plus全過程

    springboot集成mybatis-plus全過程

    本文詳細(xì)介紹了如何在SpringBoot環(huán)境下集成MyBatis-Plus,包括配置maven依賴、application.yaml文件、創(chuàng)建數(shù)據(jù)庫和Java實體類、Mapper層、Service層和Controller層的設(shè)置,同時,還涵蓋了時間自動填充、分頁查詢、多對一和一對多的數(shù)據(jù)庫映射關(guān)系設(shè)置
    2024-09-09
  • JavaSE實戰(zhàn)之酒店訂房系統(tǒng)的實現(xiàn)

    JavaSE實戰(zhàn)之酒店訂房系統(tǒng)的實現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了如何利用JavaSE實現(xiàn)酒店訂房系統(tǒng),文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)JavaSE開發(fā)有一定的幫助,需要的可以參考一下
    2022-07-07
  • JAVA接入DeepSeek滿血版的詳細(xì)指南(問答接入、流式接入雙模式)

    JAVA接入DeepSeek滿血版的詳細(xì)指南(問答接入、流式接入雙模式)

    硅基流動推出了功能完備的DeepSeek滿血版,然而眾多用戶在嘗試接入大型模型時仍面臨諸多挑戰(zhàn),特別是在流式接入方面,今天,我將引領(lǐng)大家通過Java實現(xiàn)雙模式接入DeepSeek滿血版,需要的朋友可以參考下
    2025-03-03
  • Java源碼分析:Guava之不可變集合ImmutableMap的源碼分析

    Java源碼分析:Guava之不可變集合ImmutableMap的源碼分析

    今天給大家?guī)淼氖顷P(guān)于Java源碼的相關(guān)知識,文章圍繞著Java ImmutableMap展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下,希望能給你帶來幫助
    2021-06-06
  • 利用spring的攔截器自定義緩存的實現(xiàn)實例代碼

    利用spring的攔截器自定義緩存的實現(xiàn)實例代碼

    這篇文章主要介紹了利用spring的攔截器自定義緩存的實現(xiàn)實例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • java web在高并發(fā)和分布式下實現(xiàn)訂單號生成唯一的解決方案

    java web在高并發(fā)和分布式下實現(xiàn)訂單號生成唯一的解決方案

    這篇文章主要介紹了java web在高并發(fā)和分布式下實現(xiàn)訂單號生成唯一的解決方案,需要的朋友可以參考下
    2017-11-11
  • Swing常用組件之文本框和文本區(qū)

    Swing常用組件之文本框和文本區(qū)

    這篇文章主要為大家詳細(xì)介紹了Swing常用組件之文本框(JTestField)和文本區(qū)(JTextArea),Swing是一個用于開發(fā)Java應(yīng)用程序用戶界面的開發(fā)工具包,本文開始帶大家學(xué)習(xí)Swing
    2016-05-05
  • SpringBoot+STOMP協(xié)議實現(xiàn)私聊、群聊

    SpringBoot+STOMP協(xié)議實現(xiàn)私聊、群聊

    本文將結(jié)合實例代碼,介紹SpringBoot+STOMP協(xié)議實現(xiàn)私聊、群聊,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • 重新實現(xiàn)hashCode()方法

    重新實現(xiàn)hashCode()方法

    hashCode()是Java中的一個重要方法,用于計算對象的哈希碼。本文介紹了如何重新實現(xiàn)hashCode()方法,包括使用對象的屬性計算哈希碼、使用字符串拼接計算哈希碼、使用隨機數(shù)計算哈希碼等方法。同時,還介紹了如何避免哈希沖突,提高哈希表的效率。
    2023-04-04
  • Spring Cloud Feign報錯問題解決

    Spring Cloud Feign報錯問題解決

    這篇文章主要介紹了Spring Cloud Feign報錯問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12

最新評論

确山县| 习水县| 苏尼特右旗| 富平县| 姜堰市| 临潭县| 辽阳县| 田林县| 浑源县| 革吉县| 云霄县| 新绛县| 涪陵区| 桃源县| 澄江县| 古丈县| 鄱阳县| 重庆市| 天等县| 桂东县| 平湖市| 开鲁县| 米泉市| 凤山县| 普陀区| 韶关市| 桃江县| 高平市| 潢川县| 报价| 剑川县| 丹巴县| 绍兴县| 交口县| 上高县| 刚察县| 神池县| 天门市| 吐鲁番市| 田阳县| 苗栗县|