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锁住了

相关文章
相关标签/搜索