redisTemplate寫哈希表遇到的坑

本文系原創,若有轉載,請註明出處 html

在使用spring的redisTemplate進行redis哈希表的相關操做時,遇到了下面比較奇怪的狀況:redis

  • 1.刪掉哈希表所屬的key以後,從新get這個key的值,獲得的不是null,而是一個空的map
  • 2.直接get一個不存在的key,獲得的不是null,而是一個空的map
  • 3.set進去一個null值值後,從新set一個非空的map,這個key對應的仍然是一個null

那先看一下我寫的setHash和getHashTable這兩個方法:spring

1.首先setHashTableide

public void setHashTable(final String key, Map<String, String> value) {
        Object res = redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                operations.delete(generateKey(key));
                operations.opsForHash().putAll(generateKey(key), value);
                Object val = operations.exec();
                return val;
            }
        });
        if (res == null) {
            log.error("redis transaction fail, key is : {}", key);
            throw new RuntimeException("Redis transaction fail");
        }
    }

這個方法實際上是對redisTemplate對哈希表set操做的封裝(上面實際上是用了事務操做)spa

2.getHashTabledebug

public Map<String, String> getHashTable(final String key) {
        try {
            HashOperations<String, String, String> operations = redisTemplate.opsForHash();
 Map<String, String> mapInRedis = operations.entries(generateKey(key)); return mapInRedis;
        } catch (Exception e) {
            log.warn("redis get Exception.", e);
        }
        return MapUtils.EMPTY_MAP;
    }

 好吧,針對遇到的問題,我追蹤了一下redisTemplate的源碼,debug進上面代碼中黃色的地方看一下指針

咱們能夠看到,是調用的redisTemplate.execute方法。這個方法裏面是對hGetAll的封裝調用。code

那咱們看一下redis相關文檔裏面對HGETALL的解釋:http://redisdoc.com/hash/hgetall.htmlhtm

咱們本身在終端實驗一下:blog

果真哈,輸入一個不存在的key,返回的不是null,而是一個empty list or set

那麼程序裏面返回的是{}就能夠理解了。

 

 接下來查後面set進null值的問題。咱們上述代碼中調用的是putAll方法:

看源碼能夠發現,這個方法寫着,m 不能夠爲空。若是是null有什麼後果呢

 這個方法裏面已經假定m不爲null了,直接判斷是否爲空的empty。那麼其實若是m是null,是不會走進這個方法裏面來的,至少m.isEmpty這裏會報NPE。

尚未周到具體的緣由。那我猜應該是傳入null的時候,報了空指針,某個地方攔截住而後把這個key鎖住了

相關文章
相關標籤/搜索