RedisTemplate访问Redis数据结构(三)——Hash

本文介绍如何使用Spring Data Redis中的HashOperations来操作Redis的Hash数据结构。通过实例演示了添加、批量添加、删除、检查键存在性等方法。

https://blog.youkuaiyun.com/weixin_37490221/article/details/78135036

Redis的散列可以让用户将多个键值对存储到一个Redis键里面。此处我们使用redisTemplate,配置如下(详情请见链接:RedisTemplate访问Redis数据结构(前言)

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
    <property name="connectionFactory" ref="jedisConnFactory"/>  
    <property name="keySerializer">
        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    </property>
    <property name="hashKeySerializer">
        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    </property>
    <property name="valueSerializer">
        <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
    </property>
    <property name="hashValueSerializer">
        <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
    </property>
</bean> 

HashOperations提供一系列方法操作hash。首先初始化spring工厂获得redisTemplate和opsForHash

    private RedisTemplate<String,Object> redisTemplate;
    private HashOperations<String,String,Object> opsForHash;

    @SuppressWarnings("unchecked")
    @Before
    public void before(){
        @SuppressWarnings("resource")
        ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
        redisTemplate = (RedisTemplate<String,Object>)context.getBean("redisTemplate");
        opsForHash = redisTemplate.opsForHash();
    }

void put(H key, HK hashKey, HV value);

Map< HK, HV > entries(H key);

    @Test
    public void testPut(){
        opsForHash.put("he1", "key1", "a");
        opsForHash.put("he1", "key2", "b");
        opsForHash.put("he1", "key3", "c");
        Map<String, Object> entries = opsForHash.entries("he1");
        System.out.println(entries);//{key3=c, key1=a, key2=b}(无序)
    }

void putAll(H key, Map< ? extends HK, ? extends HV > m);

    @Test
    public void testPutAll(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key1", "a");
        param.put("key2", "b");
        param.put("key3", "c");
        opsForHash.putAll("he2", param);
        System.out.println(opsForHash.entries("he2"));//{key2=b, key1=a, key3=c}
    }

Long delete(H key, Object… hashKeys);

    @Test
    public void testDelete(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key1", "a");
        param.put("key2", "b");
        param.put("key3", "c");
        opsForHash.putAll("he3", param);
        System.out.println(opsForHash.entries("he3"));//{key3=c, key2=b, key1=a}
        opsForHash.delete("he3", "key1");
        System.out.println(opsForHash.entries("he3"));//{key2=b, key3=c}
    }

Boolean hasKey(H key, Object hashKey);

    @Test
    public void testHashKey(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key1", "a");
        param.put("key2", "b");
        param.put("key3", "c");
        opsForHash.putAll("he4", param);
        System.out.println(opsForHash.hasKey("he", "key2"));//false
        System.out.println(opsForHash.hasKey("he4", "key4"));//false
        System.out.println(opsForHash.hasKey("he4", "key2"));//true
    }

HV get(H key, Object hashKey);

    @Test
    public void testGet(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key1", "a");
        param.put("key2", "b");
        param.put("key3", "c");
        opsForHash.putAll("he5", param);
        System.out.println(opsForHash.get("he5", "key1"));//a
        System.out.println(opsForHash.get("he5", "key"));//null
    }

List< HV > multiGet(H key, Collection< HK > hashKeys);

    @Test
    public void testMultiGet(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key1", "a");
        param.put("key2", "b");
        param.put("key3", "c");
        opsForHash.putAll("he6", param);
        List<String> keys = new ArrayList<String>();
        keys.add("key1");
        keys.add("key");
        keys.add("key2");
        System.out.println(opsForHash.multiGet("he6", keys));//[a, null, b]
    }

Long increment(H key, HK hashKey, long delta);

Double increment(H key, HK hashKey, double delta);

    @Test
    public void testIncrement(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key1", "a");
        param.put("key2", "b");
        param.put("key3", "c");
        param.put("key4", 4);
        opsForHash.putAll("he7", param);
        System.out.println(opsForHash.increment("he7", "key4", 1));//5
        System.out.println(opsForHash.increment("he7", "key4", 1.1));//6.1
        try {
            opsForHash.increment("he7", "key1", 1);//ERR hash value is not an integer
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            opsForHash.increment("he7", "key1", 1.1);//ERR hash value is not a float
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Set< HK > keys(H key);

    @Test
    public void testKeys(){
        redisTemplate.delete("he8");
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key4", "d");
        param.put("key1", "a");
        param.put("key3", "c");
        param.put("key5", "e");
        param.put("key2", "b");
        opsForHash.putAll("he8", param);
        Set<String> keys = opsForHash.keys("he8");
        System.out.println(keys);//[key4, key3, key5, key2, key1]
    }

Long size(H key);

    @Test
    public void testSize(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key4", "d");
        param.put("key1", "a");
        param.put("key3", "c");
        param.put("key5", "e");
        param.put("key2", "b");
        opsForHash.putAll("he9", param);
        System.out.println(opsForHash.size("he9"));//5
    }

Boolean putIfAbsent(H key, HK hashKey, HV value);

    @Test
    public void testPutIfAbsent(){
        //仅当hashKey不存在时才设置散列hashKey的值。
        System.out.println(opsForHash.putIfAbsent("he10", "key1", "a"));//true
        System.out.println(opsForHash.putIfAbsent("he10", "key1", "a"));//false
    }

List< HV > values(H key);

    @Test
    public void testValues(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key4", "d");
        param.put("key1", "a");
        param.put("key3", "c");
        param.put("key5", "e");
        param.put("key2", "b");
        opsForHash.putAll("he11", param);
        List<Object> values = opsForHash.values("he11");
        System.out.println(values);//[d, c, e, b, a]
    }

Cursor< Map.Entry< HK, HV >> scan(H key, ScanOptions options);

    @Test
    public void testScan(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("key4", "d");
        param.put("key1", "a");
        param.put("key3", "c");
        param.put("key5", "e");
        param.put("key2", "b");
        opsForHash.putAll("he13", param);
        Cursor<Map.Entry<String, Object>> curosr = opsForHash.scan("he13", ScanOptions.NONE);
        while(curosr.hasNext()){
            Map.Entry<String, Object> entry = curosr.next();
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
        /**
            key4:d
            key3:c
            key5:e
            key2:b
            key1:a
         */
    }
### RedisRepository 与 RedisTemplate 的功能及适用场景 #### 功能对比 RedisRepository 是 Spring 提供的一种基于接口定义的方式来操作 Redis 数据库的方法[^4]。通过继承 `CrudRepository` 或者 `PagingAndSortingRepository` 接口,开发者可以直接利用声明式的 API 来完成增删改查的操作。这种方式更加面向对象化,适合处理复杂的数据模型。 相比之下,RedisTemplate 则是一个更为通用的工具类,提供了丰富的 API 支持多种 Redis 数据结构(如 String、Hash、List、Set 等)。它可以执行几乎所有的 Redis 命令,并且允许开发人员自定义序列化方式以及键值存储策略[^3]。因此,在灵活性上,RedisTemplate 明显优于 RedisRepository。 #### 使用方法对比 对于 RedisRepository 而言,其使用非常简单直观,只需定义好实体类并让 Repository 接口继承相应的父接口即可自动获得一系列基础 CRUD 方法支持。例如: ```java public interface UserRepository extends CrudRepository<User, Long> { } ``` 而如果采用 RedisTemplate,则需要手动注入该 Bean 并调用具体的操作函数来实现相同的效果。下面是一段演示如何向 Redis 中写入字符串类型的例子: ```java @Autowired private RedisTemplate<String, String> redisTemplate; @Test void testSetValue(){ redisTemplate.opsForValue().set("key","value"); Assert.assertEquals("value",redisTemplate.opsForValue().get("key")); } ``` 另外值得一提的是,当涉及到缓存机制时,还可以借助像 @Cacheable 这样的注解进一步简化代码逻辑[^1]^5]。不过需要注意的是,虽然这些注解可以在一定程度上减少重复劳动量,但在某些特殊情况下可能无法满足业务需求,这时就需要回退到直接操控底层资源——即使用 RedisTemplate 实现定制化的解决方案了。 综上所述,选择哪种技术手段取决于实际应用场景和个人偏好等因素考量之后再做决定会更好一些。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值