欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java對象以Hash結(jié)構(gòu)存入Redis詳解

 更新時間:2023年08月29日 08:51:19   作者:Abstracted  
這篇文章主要介紹了Java對象以Hash結(jié)構(gòu)存入Redis詳解,和Java中的對象非常相似,卻不能按照J(rèn)ava對象的結(jié)構(gòu)直接存儲進(jìn)Redis的hash中,因為Java對象中的field是可以嵌套的,而Redis的Hash結(jié)構(gòu)不支持嵌套結(jié)構(gòu),需要的朋友可以參考下

Java對象以Hash結(jié)構(gòu)存入Redis

Redis中Hash存儲結(jié)構(gòu):

Key:{
	filed: value,
	filed: value,
	filed: value,
	....
}

和Java中的對象非常相似,卻不能按照J(rèn)ava對象的結(jié)構(gòu)直接存儲進(jìn)Redis的hash中。因為Java對象中的field是可以嵌套的,而Redis的Hash結(jié)構(gòu)不支持嵌套結(jié)構(gòu)。(不允許套娃~)。

有的同學(xué)要問了,那我就是頭鐵,就要把帶嵌套屬性的對象存儲redis的hash中,應(yīng)該怎么辦?

Spring對所有的RedisClient進(jìn)行了封裝,提供了一個RedisTemplate。那我們看看RedisTemplate中對hash結(jié)構(gòu)的存儲都接受什么參數(shù)?

在這里插入圖片描述

從圖中可以看出:

  • 一次存一個KV
  • 一次性將Map中的所有KV都存入
  • 如果不存在就存入

一次只存一個KV就不用說了。重點是第二個putAll方法。既然是Map,那我們不就是可以將帶有嵌套屬性的對象轉(zhuǎn)成Map就可以存進(jìn)Redis了嗎?

但經(jīng)過實踐最終拋出了異常。正如上面已經(jīng)說過的,Redis的Hash結(jié)構(gòu)不允許套娃。而不帶有嵌套屬性的對象轉(zhuǎn)成Map后可以正常存入。

對象轉(zhuǎn)Map可以使用commons的BeanUtils中的toMap方法。

難道真的就沒有解決辦法了嗎?其實Spring已經(jīng)為我們提供了嵌套屬性轉(zhuǎn)Map的3中實現(xiàn)方案,也就是 HashMapper 接口

在這里插入圖片描述

  • BeanUtilsHashMapper:內(nèi)部依賴commons的BeanUtils將對象轉(zhuǎn)Map,但是官方注釋中也說明了這個實現(xiàn)類不支持嵌套屬性。
  • ObjectHashMapper:內(nèi)部使用的是RedisMappingConverter將給定的Java對象提供一個平面的映射,即支持嵌套屬性。
  • Jackson2HashMapper:內(nèi)部使用的是Jackon的ObjectMapper將對象轉(zhuǎn)換成扁平的Map
  • DecoratingStringHashMapper: 沒有什么特殊的,toHash方法實現(xiàn)了裝飾器(增強)設(shè)計模式,對delegate.toHash的結(jié)果Map中的KV都進(jìn)行String.valueOf()操作。

可以看出 ObjectHashMapper 和 Jackson2HashMapper 的效果相同,用那個都可以。

注意:Jackson2HashMapper在為對象生成Map時,內(nèi)部對ObjectMapper配置了對Date類型的序列化規(guī)則,會將其換成時間戳Long類型。 在執(zhí)行putAll時,內(nèi)部會報ClassCastException Long cast to String,Long無法直接轉(zhuǎn)換為String。此時可以使用DecoratingStringHashMapper對Jackson2HashMapper進(jìn)行增強。

下面是一部分的示例代碼和截圖

@Autowired
    private RedisTemplate redisTemplate;
    /**
     * 測試Redis存Hash結(jié)構(gòu)數(shù)據(jù)
     */
    @Test
    void testSaveRedisHash() throws JsonProcessingException {
        User user = new User();user.setUserId(111);user.setPassword("psw");user.setName("張三");user.setCreateTime(new Date());
        ObjectMapper objectMapper = new ObjectMapper();
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        redisTemplate.setHashValueSerializer(RedisSerializer.string());
        // key, filed, value
        redisTemplate.opsForHash().put("testHash", "hashKey", "hashValue");
        // 直接寫JSON,并沒有什么卵用
        redisTemplate.opsForHash().put("testHash", "user", objectMapper.writeValueAsString(user));
        TestRedisHashObject testObj = new TestRedisHashObject(1, "測試時", new Date(), user);
        // 依賴第三方commons.beanUtils包
        redisTemplate.opsForHash().putAll("BeanUtilsHashMapper實現(xiàn)對象轉(zhuǎn)hash",new BeanUtilsHashMapper<>(TestRedisHashObject.class).toHash(testObj));
        // flatmap為true,才開啟json屬性path扁平化。
        // jackson2HashMapper中默認(rèn)的ObjectMapper對時間序列化成了long,而putAll方法中對long無法直接強轉(zhuǎn)成string。會發(fā)生ClassCastException
        // decoratingStringHashMapper:將map中的所有kv都使用StringValueOf進(jìn)行了增強
        redisTemplate.opsForHash().putAll("Jackson2HashMapper實現(xiàn)對象轉(zhuǎn)hash",new DecoratingStringHashMapper<>(new Jackson2HashMapper(true)).toHash(testObj));
        // ObjectHashMapper返回的Map的泛型是Map<byte[], byte[]> 需要自己手動轉(zhuǎn)換。不推薦使用
        // decoratingStringHashMapper:String.valueOf方法無法對byte[]進(jìn)行轉(zhuǎn)成字符串
        // redisTemplate.opsForHash().putAll("ObjectHashMapper實現(xiàn)對象轉(zhuǎn)hash",new ObjectHashMapper().toHash(testObj));
    }
    /**
     * 測試Redis取Hash結(jié)構(gòu)數(shù)據(jù)
     */
    @Test
    void testGetRedisHash(){
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        redisTemplate.setHashValueSerializer(RedisSerializer.string());
        String key = "Jackson2HashMapper實現(xiàn)對象轉(zhuǎn)hash";
        Object o = new Jackson2HashMapper(true).fromHash(redisTemplate.opsForHash().entries(key));
        TestRedisHashObject testObj = (TestRedisHashObject) o;
        System.out.println(testObj);
        Long newCount = redisTemplate.opsForHash().increment(key, "count", 10L);
        System.out.println("newCount = " + newCount);
        o = new Jackson2HashMapper(true).fromHash(redisTemplate.opsForHash().entries(key));
        testObj = (TestRedisHashObject) o;
        System.out.println(testObj);
		Object c = redisTemplate.opsForHash().get(key, "count");
        Long count = (Long) c;
        System.out.println("getCount = " + count);
    }

在這里插入圖片描述

在這里插入圖片描述

到此這篇關(guān)于Java對象以Hash結(jié)構(gòu)存入Redis詳解的文章就介紹到這了,更多相關(guān)Java對象存入Redis內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java語言的Comparable和Comparator區(qū)別

    Java語言的Comparable和Comparator區(qū)別

    這篇文章主要介紹了Java語言的Comparable和Comparator區(qū)別,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • JAVA發(fā)送HTTP請求的四種方式總結(jié)

    JAVA發(fā)送HTTP請求的四種方式總結(jié)

    這篇文章主要給大家介紹了關(guān)于JAVA發(fā)送HTTP請求的多種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Java數(shù)據(jù)類型的全面剖析

    Java數(shù)據(jù)類型的全面剖析

    這篇文章主要介紹了Java基本數(shù)據(jù)類型,結(jié)合實例形式詳細(xì)分析了java基本數(shù)據(jù)類型、數(shù)據(jù)類型范圍、易錯題等相關(guān)原理與操作技巧,需要的朋友可以參考下
    2021-10-10
  • java獲取兩個數(shù)組中不同數(shù)據(jù)的方法

    java獲取兩個數(shù)組中不同數(shù)據(jù)的方法

    這篇文章主要介紹了java獲取兩個數(shù)組中不同數(shù)據(jù)的方法,實例分析了java操作數(shù)組的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-03-03
  • SpringBoot整合GRPC微服務(wù)遠(yuǎn)程通信的實現(xiàn)示例

    SpringBoot整合GRPC微服務(wù)遠(yuǎn)程通信的實現(xiàn)示例

    本文主要介紹了SpringBoot整合GRPC微服務(wù)遠(yuǎn)程通信的實現(xiàn)示例,包含gRPC的工作原理,以及如何在Spring Boot應(yīng)用中集成gRPC,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • java實現(xiàn)Floyd算法

    java實現(xiàn)Floyd算法

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)Floyd算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • RocketMQ中的NameServer詳細(xì)解析

    RocketMQ中的NameServer詳細(xì)解析

    這篇文章主要介紹了RocketMQ中的NameServer詳細(xì)解析,NameServer是一個非常簡單的Topic路由注冊中心,支持Broker的動態(tài)注冊與發(fā)現(xiàn),因此不能保證NameServer的一致性,需要的朋友可以參考下
    2024-01-01
  • SpringBoot中的定時任務(wù)和異步調(diào)用詳解

    SpringBoot中的定時任務(wù)和異步調(diào)用詳解

    這篇文章主要介紹了SpringBoot中的定時任務(wù)和異步調(diào)用詳解,SpringBoot 定時任務(wù)是一種在SpringBoot應(yīng)用中自動執(zhí)行任務(wù)的機(jī)制,通過使用Spring框架提供的@Scheduled注解,我們可以輕松地創(chuàng)建定時任務(wù),需要的朋友可以參考下
    2023-10-10
  • 詳解elasticsearch實現(xiàn)基于拼音搜索

    詳解elasticsearch實現(xiàn)基于拼音搜索

    這篇文章主要為大家介紹了詳解elasticsearch實現(xiàn)基于拼音搜索示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Java使用BigDecimal解決小數(shù)計算問題

    Java使用BigDecimal解決小數(shù)計算問題

    Java中的BigDecimal是一個內(nèi)置類,用于精確表示任意大小的十進(jìn)制數(shù),它提供了一種處理浮點運算精度問題的方法,特別適合金融、貨幣交易等需要高精度計算的場景,本文給大家介紹了java中如何使用BigDecimal解決小數(shù)計算問題,需要的朋友可以參考下
    2024-08-08

最新評論