springboot使用RedisTemplate操作Redis数据库

一.什么是Redis

Redis是一个非关系型数据库,具有很高的存取性能,一般用作缓存数据库,减少正常存储数据库的压力。

Redis可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。

二.RedisTemplate及其相关方法

Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。
注意 RedisTemplate是一个key和value都是泛型的模板类,一般情况下key为String类型,如:RedisTemplate<String,Object>。
此外,如果没特殊情况,切勿定义成RedisTemplate<Object, Object>,否则根据里氏替换原则,使用的时候会造成类型错误 。

// 在maven中添加依赖(下面只是主要的部分依赖)
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

spring-data-redis针对jedis提供了如下功能:
1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2.针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作

RedisTemplate中定义了对5种数据结构操作
redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
其实这里的ops相当于options, 是RedisTemplate对各种不同的Redis数据类型进行操作。其实还有另外的方法:
redistempalate.boundValueOps
redistempalate.boundSetOps
redistempalate.boundListOps
redistempalate.boundHashOps
redistempalate.boundZSetOps
opsForXXX和boundXXXOps的区别?

前者获取一个operator,但是没有指定操作的对象(key),可以在一个连接(事务)内操作多个key以及对应的value;后者获取了一个指定操作对象(key)的operator,在一个连接(事务)内只能操作这个key对应的value。
关于计数的API(increment)有一个bug,需要各位使用中注意,通过increment计数以后,通过get方式获取计数值的时候可能会抛出EOF异常(和本地的jdk以及redis的编译版本有关),可以考虑使用boundValueOps(key).get(0,-1)获取计数值。

三.RedisTemplate操作Redis数据库的具体例子

1、Value(值)类型

public class RedisTest {
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testValue(){
        redisTemplate.boundValueOps("testValue1").set("value1",60,TimeUnit.SECONDS); //设置过期时间为60秒,60秒后自动删除
        redisTemplate.boundValueOps("testValue2").set("value2");
//        redisTemplate.boundValueOps("testValue2").set("22222",3); //把testValue2的前三位置换为22222
    }

    @Test
    public void getValue(){
        Object o1 = redisTemplate.boundValueOps("testValue1").get();
        Object o2 = redisTemplate.boundValueOps("testValue2").get();
        System.out.println(o1 + " "  + o2);

    }
}

2、list类型

   @Test
   public void listTest(){
       redisTemplate.boundListOps("list").leftPush("aaa");
       redisTemplate.boundListOps("list").leftPush("aaa");
       redisTemplate.boundListOps("list").leftPush("aaa");
       redisTemplate.boundListOps("list").leftPush("bbb");
       redisTemplate.boundListOps("list").rightPush("ccc");
       redisTemplate.boundListOps("list").rightPush("ddd");

   }

   @Test
   public void getList(){
       List list = redisTemplate.boundListOps("list").range(0,10); //查询,range(0,10)会查询出0-10的元素
       System.out.println(list);
       System.out.println(redisTemplate.boundValueOps("list").getKey()); //获取key值
       redisTemplate.boundListOps("list").remove(2,"aaa"); //删除两个个aaa

       List list1 = redisTemplate.boundListOps("list").range(0,10); //查询,range(0,10)会查询出0-10的元素
       System.out.println(list1);
       redisTemplate.boundListOps("list").expire(60,TimeUnit.SECONDS); //设置60秒后过期

       System.out.println(redisTemplate.boundListOps("list").index(1)); //根据索引获取值
       System.out.println(redisTemplate.boundListOps("list").leftPop()); //bbb,打印左边起第一个元素值
	}
	
	/**
	 * 右压栈:后添加的对象排在后边,相当于队列,相当于先进先出
	 */
	@Test
	public void testSetValue1(){		
		redisTemplate.boundListOps("namelist1").rightPush("刘备");
		redisTemplate.boundListOps("namelist1").rightPush("关羽");
		redisTemplate.boundListOps("namelist1").rightPush("张飞");		
	}
	
	/**
	 * 显示右压栈集合,range 表示查询的索引,从第几个查到第几个,如果想查询所有的数的话只能将第二个数写得大一点。
	 */
	@Test
	public void testGetValue1(){
		List list = redisTemplate.boundListOps("namelist1").range(0, 10);
		System.out.println(list);
	}
	//运行结果:[刘备, 关羽, 张飞],元素可以重复
	
	/**
	 * 左压栈:后添加的对象排在前边,相当于栈,先进后出
	 */
	@Test
	public void testSetValue2(){		
		redisTemplate.boundListOps("namelist2").leftPush("刘备");
		redisTemplate.boundListOps("namelist2").leftPush("关羽");
		redisTemplate.boundListOps("namelist2").leftPush("张飞");		
	}
	
	/**
	 * 显示左压栈集合
	 */
	@Test
	public void testGetValue2(){
		List list = redisTemplate.boundListOps("namelist2").range(0, 10);
		System.out.println(list);
	}
	//运行结果:[张飞, 关羽, 刘备]

3、set类型:无序、不可重复

@Test
    public void setTest(){
        redisTemplate.boundSetOps("set").add("aaa");
        redisTemplate.boundSetOps("set").add("bbb");
        redisTemplate.boundSetOps("set").add("ccc");
        redisTemplate.boundSetOps("set").add("ddd");
    }

    @Test
    public void getTest(){
        Set set = redisTemplate.boundSetOps("set").members();
        System.out.println(set); //[bbb, ccc, aaa, ddd]
        redisTemplate.boundSetOps("set").remove("aaa");//删除aaa这个元素
        redisTemplate.delete("set"); //删除整个集合
    }

4、ZSet

@Test
    public void zsetTest(){
        redisTemplate.boundZSetOps("zset").add("aaa",1);
        redisTemplate.boundZSetOps("zset").add("bbb",2);
        redisTemplate.boundZSetOps("zset").add("ccc",3);
        redisTemplate.boundZSetOps("zset").add("ddd",4);
    }

    @Test
    public void getTest(){
        Set zset = redisTemplate.boundZSetOps("zset").range(0,10);
        System.out.println(zset); //[aaa, bbb, ccc, ddd]

        redisTemplate.boundZSetOps("zset").removeRange(0,2); //删除0-2的元素,共三个

        Set zset1 = redisTemplate.boundZSetOps("zset").range(0,10);
        System.out.println(zset1); //[ddd]

    }

5、hash类型

@Test
    public void hashTest(){
        redisTemplate.boundHashOps("hash").put("1", "a");
        redisTemplate.boundHashOps("hash").put("2", "b");
        redisTemplate.boundHashOps("hash").put("3", "c");
        redisTemplate.boundHashOps("hash").put("4", "d");
    }
    

    @Test
    public void getHashTest(){
        List hash = redisTemplate.boundHashOps("hash").values();
        System.out.println(hash);

        Set set = redisTemplate.boundHashOps("hash").keys();
        System.out.println(set);

        Object o = redisTemplate.boundHashOps("hash").get("1");
        System.out.println(o);

        /**
         * [a, b, c, d]
         * [1, 2, 3, 4]
         * a
         */
    }
注意:上面五种类型都可以使用redisTemeplate的expire(long l,TimeUnit timeUnit)函数设置过期时间。

四.RedisTemplate和StringRedisTemplate的区别

1、StringRedisTemplate继承RedisTemplate;

2、两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据

3、序列化方式不同
StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的;
RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。
RedisTemplate使用的序列类在在操作数据的时候,比如说存入数据会将数据先序列化成字节数组然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式展现的,而是以字节数组显示。
当然从Redis获取数据的时候也会默认将数据当做字节数组转化,这样就会导致一个问题,当需要获取的数据不是以字节数组存在redis当中而是正常的可读的字符串的时候。
RedisTemplate就无法获取导数据,这个时候获取到的值就是NULL。这个时候StringRedisTempate就派上了用场。

当Redis当中的数据值是以可读的形式显示出来的时候,只能使用StringRedisTemplate才能获取到里面的数据。

所以当你使用RedisTemplate获取不到数据的时候请检查一下是不是Redis里面的数据是可读形式而非字节数组。

参考网址:
https://blog.csdn.net/qq_43060759/article/details/90707626
https://www.cnblogs.com/EasonJim/p/7803067.html
https://blog.csdn.net/striveb/article/details/83745680

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值