本文系原创,如有转载,请注明出处

在使用spring的redisTemplate进行redis哈希表的相关操作时,遇到了下面比较奇怪的情况:

  • 1.删掉哈希表所属的key之后,重新get这个key的值,得到的不是null,而是一个空的map
  • 2.直接get一个不存在的key,得到的不是null,而是一个空的map
  • 3.set进去一个null值值后,重新set一个非空的map,这个key对应的仍然是一个null

那先看一下我写的setHash和getHashTable这两个方法:

1.首先setHashTable

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操作的封装(上面其实是用了事务操作)

2.getHashTable

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的封装调用。

那我们看一下redis相关文档里面对HGETALL的解释:http://redisdoc.com/hash/hgetall.html

我们自己在终端实验一下:

果然哈,输入一个不存在的key,返回的不是null,而是一个empty list or set

那么程序里面返回的是{}就可以理解了。

接下来查后面set进null值的问题。我们上述代码中调用的是putAll方法:

看源码可以发现,这个方法写着,m 不可以为空。如果是null有什么后果呢

这个方法里面已经假定m不为null了,直接判断是否为空的empty。那么其实如果m是null,是不会走进这个方法里面来的,至少m.isEmpty这里会报NPE。

还没有周到具体的原因。那我猜应该是传入null的时候,报了空指针,某个地方拦截住然后把这个key锁住了

redisTemplate写哈希表遇到的坑的更多相关文章

  1. [Codevs 1230]元素查找(手写哈希表)

    题目连接:http://codevs.cn/problem/1230/ 说白了就是要我们自己手写一个哈希表的数据结构来实现加入和查找功能.map也能直接过(我第一次写就是用map骗AC的) 提一下个人 ...

  2. PTA 7-42 整型关键字的散列映射(手写哈希表的线性探测法)

    本题考点: 整型哈希表的线性探测法 给定一系列整型关键字和素数P,用除留余数法定义的散列函数将关键字映射到长度为P的散列表中.用线性探测法解决冲突. 输入格式: 输入第一行首先给出两个正整数N(≤10 ...

  3. 哈希表的C实现(三)---传说中的暴雪版

    关于哈希表C实现,写了两篇学习笔记,不过似乎网上流传最具传奇色彩的莫过于暴雪公司的魔兽文件打包管理器里的hashTable的实现了:在冲突方面的处理方面,采用线性探测再散列.在添加和查找过程中进行了三 ...

  4. LeetCode通关:哈希表六连,这个还真有点简单

    精品刷题路线参考: https://github.com/youngyangyang04/leetcode-master https://github.com/chefyuan/algorithm-b ...

  5. 【哈希表】CodeVs1230元素查找

    一.写在前面 哈希表(Hash Table),又称散列表,是一种可以快速处理插入和查询操作的数据结构.哈希表体现着函数映射的思想,它将数据与其存储位置通过某种函数联系起来,其在查询时的高效性也体现在这 ...

  6. 漫谈Linux内核哈希表(1)

    关于哈希表,在内核里设计两个很重要的数据结构:    哈希链表节点: 点击(此处)折叠或打开 .x [include/linux/types.h]*/ struct hlist_node { stru ...

  7. noip模拟赛 好元素 哈希表的第一题

    这是一道关于 题2好元素 2s [问题描述] 小A一直认为,如果在一个由N个整数组成的数列{An}中,存在以下情况: Am+An+Ap = Ai (1 <= m, n, p < i < ...

  8. c# 哈希表跟函数

    一.哈希表集合 先进后出,一个一个赋值,但只能一起取值. 1.哈希表的建立.赋值以及读取. 2.利用枚举类型打印出集合中的Key值和Value值. 二.函数 函数:能够独立完成某项功能的模块. 函数四 ...

  9. Redis哈希表的实现要点

    Redis哈希表的实现要点 哈希算法的选择 针对不同的key使用不同的hash算法,如对整型.字符串以及大小写敏感的字符串分别使用不同的hash算法: 整型的Hash算法使用的是Thomas Wang ...

随机推荐

  1. java自带线程池和队列详细讲解<转>

    Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后 ...

  2. rsync详解之exclude排除文件

    rsync详解之exclude排除文件 问题:如何避开同步指定的文件夹?  --excludersync  --exclude files and folders http://articles.sl ...

  3. android之SQLite数据库insert操作

    原型: long Android.database.sqlite.SQLiteDatabase.insert(String table, String nullColumnHack, ContentV ...

  4. 代码生成利器:IDEA 强大的 Live Templates

    Java 开发过程经常需要编写有固定格式的代码,例如说声明一个私有变量, logger 或者 bean 等等.对于这种小范围的代码生成,我们可以利用 IDEA 提供的 Live Templates 功 ...

  5. mysql的优化基础知识

    1.查看各种SQL执行的频率 mysql> show status like 'Com_select';--Com_insert,Com_delete,connections(试图连接mysql ...

  6. RESTful作用与特性

    最近在项目中要使用rest风格的设计,学习了一下. 知乎网友说的一句话精确的解释了REST: URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作-(https://ww ...

  7. Spring_day04--SSH框架整合过程

    SSH框架整合过程 第一步 导入jar包 第二步 搭建struts2环境 (1)创建action,创建struts.xml配置文件,配置action (2)配置struts2的过滤器 第三步 搭建hi ...

  8. 编程之美 海量数据寻找 K 大数

    1. 使用最小堆, 设置最小堆的大小为K, 仅需遍历一遍即可 2. 寻找最大的 K 个数实质上是寻找第 K 大的数. 通过二分法在区间内不断校正 mid 的值来找到 pivot, 时间复杂度为 o(N ...

  9. springboot整合mybatis之用外置服务器启动项目(二)

    在上一篇中我们是用的springboot自带的tomcat服务器,接下来想试一下 将springboot当做一个web项目 放在eclipse中用tomcat来启动. 首先在pom.xml中加上,移除 ...

  10. $("#btn").click(function(){ });只有在页面加载的时候才会有效触发

    例: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title& ...