使用Spring RedisTemplate操作list元素时不弹出(删除)只进行获取

今天做一个小项目要用到redis查询,遇到一个很奇怪的现象:
使用redis缓存一个list,然而我发现每次缓存完后,第二次获取是正常的,第三次的时候缓存就又丢了,如此反复。
代码如下:

public List<ItemCat> selectAllByStatus(int status) {
        List<ItemCat> itemCats = null;
        try {
            //从redis中获取存放分类信息的缓存
            itemCats = (List<ItemCat>) redisTemplate.opsForList().leftPop("itemCats",0,0);
            //没有缓存,从数据库中获取并存入缓存
            if(itemCats==null || itemCats.isEmpty()){
                itemCats = itemCatMapper.selectAllByStatus(status);
                redisTemplate.opsForList().leftPush("itemCats",itemCats);
            }
        } catch (Exception e) {
            //连接服务器有异常
            itemCats = itemCatMapper.selectAllByStatus(status);
            e.printStackTrace();
        } finally {
            return itemCats;
        }
    }

我越看越奇怪,虽然是spring提供的redis工具,但是leftPop应该和原生指令是一致的也即是:LPop指令

LPOP key
移除并返回列表 key 的头元素。
可用版本:= 1.0.0
时间复杂度:
O(1)
返回值:
列表的头元素。
当 key 不存在时,返回 nil 。

pop是弹出操作,弹出后回删此元素,也就解释了为什么会一次有缓存一次没有缓存的问题。


解决思路:查阅了redis的api,想起来获取而不删除的命令应该是range,再去翻阅spring RedisTemple的api文档,果然有range方法。

下面是来自didier-spezia的回答

You can easily peek at an item rather than popping it by using the range command.
With Spring, from a RedisTemplate instance, you can get a ListOperations instance by using the opsForList() method, and then:
listOp.range(key, 0, 0) will return the first (left) item without popping it
listOp.range(key, -1, -1) will return the last (right) item without popping it
See documentation at:
http://static.springsource.org/spring-data/data-keyvalue/docs/1.0.x/api/org/springframework/data/keyvalue/redis/core/RedisTemplate.html
http://static.springsource.org/spring-data/data-keyvalue/docs/1.0.x/api/org/springframework/data/keyvalue/redis/core/ListOperations.html

大致意思是,如果想根据key获取某个元素,应该是使用 listOp.range(key, 0, 0)方法或者 listOp.range(key, -1, -1),主要区别是一个是从第一个(左边)还是从最后一个(右边)位置来获取。

//将leftPop改为range方法就欧克
itemCats = (List<ItemCat>) redisTemplate.opsForList().range("itemCats",0,0);

2020-11-7更新:经测试后发现range方法把list封装过一次,导致前端有问题,新的解决思路是:使用index方法!!

  //从redis中获取存放分类信息的缓存 要用index方法!!!!
 	itemCats = (List<ItemCat>) redisTemplate.opsForList().index("itemCats",-1);

参考链接:https://stackoverflow.com/questions/10882713

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: redistemplate操作list是指在Redis使用redistemplate对象对list类型的数据进行操作redistemplateSpring Data Redis提供的一个操作Redis的模板类,可以方便地进行Redis操作。对于list类型的数据,redistemplate提供了以下操作: 1.向list中添加元素使用redistemplate.opsForList().rightPush(key, value)方法可以向list的右侧添加元素使用redistemplate.opsForList().leftPush(key, value)方法可以向list的左侧添加元素。 2.获取list中的元素使用redistemplate.opsForList().range(key, start, end)方法可以获取list中从start到end的元素使用redistemplate.opsForList().index(key, index)方法可以获取list中指定位置的元素。 3.删除list中的元素使用redistemplate.opsForList().remove(key, count, value)方法可以删除list中指定的元素使用redistemplate.opsForList().trim(key, start, end)方法可以删除list中从start到end以外的元素。 4.获取list的长度:使用redistemplate.opsForList().size(key)方法可以获取list的长度。 以上就是redistemplate操作list的一些常用方法。 ### 回答2: redis是一种高性能、基于内存的键值对存储数据库,它支持多种数据结构类型,包括String、Hash、List、Set、Sorted Set等。在redis中,List是一种底层双向链表数据结构,它具有快速访问表头、表尾元素和随机访问能力等优点。 而redistemplate则是Spring Framework对redis进行操作的一种模板类,可以简化redis操作流程并提高开发效率。在redistemplate中,List操作包括插入、删除、修改、查询等操作方法。 首先,插入操作是通过对表头或表尾进行push/pop操作来实现的。redistemplate提供了四种插入方法:leftPush、rightPush、leftPushAll、rightPushAll。其中,leftPush和rightPush分别表示插入一个元素到表头和表尾,leftPushAll和rightPushAll则表示插入多个元素到表头和表尾。 接着,删除操作是通过对表头或表尾进行操作来实现的。redistemplate提供了两种删除方法:leftPop和rightPop,分别表示从表头和表尾弹一个元素。 修改操作比较复杂,需要先删除原有元素,再插入新元素redistemplate提供了两种修改方法:set和setIfAbsent。其中,set方法表示修改指定下标的元素为新元素,setIfAbsent方法则表示当下标处不存在元素时才进行修改。 最后,查询操作是通过遍历整个List来实现的。redistemplate提供了四种查询方法:range、size、index、leftPopAndPush。其中,range方法用于查询指定下标范围内的元素列表,在redis中,下标从0开始算起;size方法用于查询List的长度;index方法用于查询指定下标处的元素;leftPopAndPush方法则用于将表头元素,并插入到另一个List表头处,实现元素移动功能。 总之,通过redistemplate操作List是一种方便快捷的方式,可以大大提高开发效率。在实际应用中,需要根据场景选择合适的操作方法,并注意数据类型转换和事务处理等细节。 ### 回答3: redis是一个高性能的key-value储存系统,而redistemplate是基于redis的Java客户端库,简化了对redis操作操作listredis中的一种数据结构,其用途类似于Java中的ArrayList,但其具有特殊的相对于其他数据结构的操作redistemplate可以通过以下的两种方式进行list操作: 1. 用于list元素操作有:lPush(从list左侧插入一个元素)、rPush(从list右侧插入一个元素)、lPop(从list左侧弹一个元素)、rPop(从list右侧弹一个元素)、lLen(获取list的长度)、lIndex(获取list中指定位置的元素值)、lRange(获取list指定区间的元素)、lTrim(截取list指定区间的元素)、lSet(替换list指定位置的元素)、lRem(删除list中指定个数的指定元素)。使用示例如下: ListOperations<String, String> listOperations = redisTemplate.opsForList(); // 从list左侧插入元素 listOperations.leftPush("myList", "1"); // 获取list的长度 long len = listOperations.size("myList"); // 获取list的第一个元素 String firstElement = listOperations.index("myList", 0); // 获取list的前三个元素 List<String> firstThreeElements = listOperations.range("myList", 0, 2); // 删除list的前两个元素,返回删除的个数 long removedCount = listOperations.remove("myList", 2, "1"); 2. 用于list的批量操作有:lPushAll(从list左侧插入多个元素)、rPushAll(从list右侧插入多个元素)、lRemAll(删除list中所有现的指定元素)。使用示例如下: ListOperations<String, String> listOperations = redisTemplate.opsForList(); // 从list左侧插入多个元素 listOperations.leftPushAll("myList", "1", "2", "3"); // 从list右侧插入多个元素 listOperations.rightPushAll("myList", "4", "5", "6"); // 删除list中所有现的指定元素 listOperations.remove("myList", -1, "1"); 总的来说,redistemplatelist操作包括了对list元素插入、删除获取、截取等常规操作,也包括了对list的批量操作。因此,使用redistemplate可以更加便捷地操作redis中的list
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值