redis系列:通过demo学习hash命令

前言

这一篇文章将讲述Redis中的hash类型命令,同样也是通过demo来讲述,其他部分这里就不在赘述了。

项目Github地址:https://github.com/rainbowda/learnWay/tree/master/learnRedis/case-hash

案例

demo功能是记录日志,整个demo的大致页面如下

[图片上传失败...(image-6b455b-1532305707382)]

准备工作

首先定义一个key的前缀,已经存储自增id的key

private static final String CONTACTS_KEY_PREFIX = "contacts:";
private static final String CONTACTS_ID_KEY = "contactsID";

通讯录相关的key将会以contacts:1、contacts:2、contacts:3的形式存储

redis操作对象

private RedisTemplate redisTemplate;
//string 命令操作对象
private ValueOperations valueOperations;
//hash 命令操作对象
private HashOperations hashOperatio

疑惑

如果读者和我一样是学Java的,刚听到hash时的第一反应是这个不是一个算法吗?当时我也是这样想的。那么先来看看hash在Redis中的结构,如下图(图片来源于Redis in Action)。

[图片上传失败...(image-efbc1c-1532305707383)]

如果图看不懂的,我再来介绍下。其实Redis中的hash结构就和mysql中的表类似,把key当做表名,一张表中有多个列名(sub-key),每个列有自己的值(value),然后这张表只能存放一条数据。不过,这里的hash结构不会像mysql中固定好的,它可以很方便的增加删除列,例如增加sub-key3删除sub-key1.

[图片上传失败...(image-304bf3-1532305707383)]

新增

命令介绍

先来看看hash中关于新增的一些命令

命令 用例 描述
HSET HSET key field value 设置 key 指定的哈希集中指定字段的值。
HSETNX HSETNX key field value 当field不存在时,才能成功设置值
HMSET HMSET key field value [field value ...] 设置 key 指定的哈希集中指定字段的值(多个) 。

接下来看看demo中新增的功能,下图中点击+按钮,然后在弹出框中填入name和phone属性,点击提交后整个新增流程结束。

[图片上传失败...(image-f43563-1532305707383)]

来看看后台的方法

@RequestMapping(value = "/add",method = RequestMethod.POST)
public boolean add(@RequestBody JSONObject contacts){
    //获取自增id
    Long contactsId = valueOperations.increment(CONTACTS_ID_KEY, 1);

    contacts.put("id",String.valueOf(contactsId));
    //json转map,然后存入redis
    hashOperations.putAll(CONTACTS_KEY_PREFIX+contactsId,contacts.getInnerMap());

    return true;
}
  1. 首先是获得自增id

  2. 然后将id存入到前端传过来的json对象中

  3. 调用hashOperations对象的putAll方法将对象传入到Redis中。(putAll方法其实是调用了hmset命令,源码如下)

public void putAll(K key, Map<? extends HK, ? extends HV> m) {
    if (!m.isEmpty()) {
        byte[] rawKey = this.rawKey(key);
        Map<byte[], byte[]> hashes = new LinkedHashMap(m.size());
        Iterator var5 = m.entrySet().iterator();

        while(var5.hasNext()) {
            Entry<? extends HK, ? extends HV> entry = (Entry)var5.next();
            hashes.put(this.rawHashKey(entry.getKey()), this.rawHashValue(entry.getValue()));
        }
        //调用hMSet
        this.execute((connection) -> {
            connection.hMSet(rawKey, hashes);
            return null;
        }, true);
    }
}

列表查询

命令介绍

同样先看看相关的获取值命令

命令 用例 描述
HGET HGET key field 返回 key 指定的哈希集中该字段所关联的值
HGETALL HGETALL key 返回 key 指定的哈希集中所有的字段和值。
HKEYS HKEYS key 返回 key 指定的哈希集中所有字段的名字。
HMGET HMGET key field [field ...] 返回 key 指定的哈希集中指定字段的值。
HVALS HVALS key 返回 key 指定的哈希集中所有字段的值。
HSCAN 用于迭代Hash类型中的键值对。
HGET和HGETALL命令

来看看HGET和HGETALL在redis客户端和java中是如何操作的

redis客户端执行的命令如下

hset key field1 "Hi"
hset key field1 "Hello"
hsetnx key field1 "Hello"
hsetnx key field2 " redis"
hget key field1
hgetall key

执行结果如下

[图片上传失败...(image-cd5924-1532305707383)]

下面是java代码

@Test
public void hGetAll() {
    jedis.hset("key", "field1", "Hi");
    redisTemplate.opsForHash().put("key", "field1", "Hello");

    System.out.println(jedis.hsetnx("key", "field1", "Hello"));
    System.out.println(redisTemplate.opsForHash().putIfAbsent("key", "field2", "Hello"));

    System.out.println(jedis.hget("key", "field1"));
    System.out.println(jedis.hgetAll("key"));

    //spring redisTemplate
    System.out.println(redisTemplate.opsForHash().get("key", "field1"));
    System.out.println(redisTemplate.opsForHash().entries("key"));
}
HKEYS

redis客户端执行的命令如下

hset hashKey field1 value1
hset hashKey field2 value2
hkeys hashKey

执行结果如下

[图片上传失败...(image-dece11-1532305707383)]

下面是java代码

@Test
public void hKeys() {
    jedis.hset("hashKey", "field1", "value1");
    jedis.hset("hashKey", "field2", "value2");

    System.out.println(jedis.hkeys("hashKey"));

    //spring redisTemplate
    System.out.println(redisTemplate.opsForHash().keys("hashKey"));
    /**
     * 注:两次结果返回的顺序是不一样的,
     * 因为jedis.hkeys返回的是HashSet(内部使用HashMap)
     * redisTemplate.opsForHash().keys返回的是LinkHashSet(内部使用LinkHashMap)
     */
}
HVALS

redis客户端执行的命令如下

hmset key field1 value1 field2 value2 field3 value3
hvals key

执行结果如下

[图片上传失败...(image-da4faa-1532305707383)]

下面是java代码

@Test
public void hVals() {
    Map<String, String> map = new HashMap<>(3);
    map.put("field1", "value1");
    map.put("field2", "value2");
    map.put("field3", "value3");

    jedis.hmset("key", map);

    System.out.println(jedis.hvals("key"));

    //spring redisTemplate
    System.out.println(redisTemplate.opsForHash().values("key"));
}

查询方法代码

接着写个查询方法,将新增的内容查询出来

@RequestMapping(value = "/getList",method = RequestMethod.GET)
    public List getList(){
        List list = new ArrayList();

        //获取联系人的keys
        Set<String> keys = redisTemplate.keys(CONTACTS_KEY_PREFIX+"*");

        for (String key: keys) {
            Map entries = hashOperations.entries(key);
            list.add(entries);
        }

        return list;
    }

这个hash查询多个会不方便些,步骤如下

  1. 获取相关的key
  2. 循环查找key相关的数据
  3. 将查询出来的结果添加到list中,返回

添加属性

[图片上传失败...(image-e2527f-1532305707383)]

来看看代码

@RequestMapping(value = "/addAttr", method = RequestMethod.POST)
public boolean addAttr(@RequestBody JSONObject contacts){
    String id = contacts.getString("id");
    String fieldName = contacts.getString("fieldName");
    String fieldValue = contacts.getString("fieldValue");

    hashOperations.put(CONTACTS_KEY_PREFIX+id, fieldName, fieldValue);

    return true;
}

其实就是用hset命令进行插入

hset contacts:1 address 北京9527号

删除属性

命令介绍

命令 用例 描述
HDEL HDEL key field [field ...] 从 key 指定的哈希集中移除指定的域

redis客户端执行的命令如下

hset hDelKey filed1 filedValue1
hdel hDelKey filed1
hdel hDelKey filed1

执行结果如下

[图片上传失败...(image-48da45-1532305707383)]

现在来看看demo中的删除属性

[图片上传失败...(image-19210f-1532305707383)]

代码如下

@RequestMapping(value = "/delAttr", method = RequestMethod.POST)
public boolean delAttr(@RequestBody JSONObject contacts){

    String id = contacts.getString("id");
    String fieldName = contacts.getString("fieldName");
    hashOperations.delete(CONTACTS_KEY_PREFIX+id, fieldName);

    return true;
}

其他命令

命令 用例 描述
HEXISTS HEXISTS key field 返回hash里面field是否存在
HINCRBY HINCRBY key field increment 增加 key 指定的哈希集中指定字段的数值
HINCRBYFLOAT HINCRBYFLOAT key field increment 同上,加的是浮点型
HLEN HLEN key 返回 key 指定的哈希集包含的字段的数量。
HSTRLEN HSTRLEN key field 返回hash指定field的value的字符串长度

建议学习的人最好每个命令都去敲下,加深印象。下面诗句送给你们。

纸上得来终觉浅,绝知此事要躬行。————出自《冬夜读书示子聿》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容

  • 前言 该文章将通过一个小demo将讲述Redis中的string类型命令。demo将以springboot为后台框...
    东西的南北阅读 428评论 0 0
  • 文章已经放到github上 ,如果对您有帮助 请给个star[https://github.com/qqxuanl...
    尼尔君阅读 2,284评论 0 22
  • 1 月快要沉下去了,更漏的声音越来越悠长。我把门虚掩着,窗外乌鸦好像在嘲笑...
    桑璇阅读 337评论 0 2
  • 常海沧老师讲的热性体质面临的疾病,最常见的是高血压 糖尿病 心脑血管疾病 这些疾病人们认为跟家族有关系,这是完全错...
    云少nn阅读 167评论 0 0
  • 我非常喜欢《甄嬛传》这部剧。一开始只是想看看一个单纯的女孩如何成长为一个腹黒女王,在遭受一系统打击后,如何逆袭上位...
    不管三八二十四阅读 179评论 0 0