前面节分别介绍了 ValueOperations、SetOperations、ZSetOperations、ListOperations、HyperLogLogOperations 等操作接口。这些操作接口都拥有一个共性,在进行某个具体操作时,都需要传递 key,例如:使用这些操作接口添加值时,如下:
SetOperations -> add(K key, V... values) ZSetOperations -> add(K key, Set<ZSetOperations.TypedTuple<V>> tuples) ValueOperations -> set(K key, V value) ListOperations -> leftPush(K key, V value) ListOperations -> rightPush(K key, V value) ...
其实我们整个操作过程中,可能并没有换 key,反复就对一个 key 进行设置、取值、删除操作。于是,Spring Data Redis 提供了一套 Bound 类型的便捷操作接口,这些接口提前将某个 key 和操作接口进行绑定,在使用 Bound 接口进行操作时,就不需要传递麻烦的 key 了。
在 Spring Data Redis 的 RedisTemplate 类中,通过如下方法获取不同类型的 Bound 操作接口,如下:
BoundGeoOperations<K,V> boundGeoOps(K key) 返回绑定到给定键的地理空间特定操作接口。
<HK,HV> BoundHashOperations<K,HK,HV> boundHashOps(K key) 返回对绑定到给定键的哈希值执行的操作。
BoundListOperations<K,V> boundListOps(K key) 返回对绑定到给定键的列表值执行的操作。
BoundSetOperations<K,V> boundSetOps(K key) 返回对绑定到给定键的集合值执行的操作。
BoundValueOperations<K,V> boundValueOps(K key) 返回对绑定到给定键的简单值(或 Redis 术语中的字符串)执行的操作。
BoundZSetOperations<K,V> boundZSetOps(K key) 返回对绑定到给定键的 zset 值(也称为排序集)执行的操作。
下面通过一些列的具体示例演示怎样快速利用 Bound 类型操作接口操作 GEO、Hash、List、Set、Value、ZSet 数据类型。
BoundValueOperations<String,String> ops = redisTemplate.boundValueOps("bound-value"); // 新增 ops.set("value1"); System.out.println(ops.get()); // 修改 ops.set("value2"); System.out.println(ops.get()); // 追加值 ops.append(" append"); System.out.println(ops.get()); // 设置过期时间 ops.set("value3", 5, TimeUnit.SECONDS); System.out.println(ops.get()); try { // 休眠6秒,再次获取值 Thread.sleep(6000); System.out.println(ops.get()); } catch (Exception e) {}
运行结果:
value1 value2 value2 append value3 null
BoundHashOperations<String,String,String> ops = redisTemplate.boundHashOps("bound-hash"); // 新增 ops.put("k1", "v1"); ops.put("k2", "100"); ops.put("k3", "v3"); System.out.println(JSONObject.toJSONString(ops.entries())); // 增加 ops.increment("k2", 10); System.out.println("k2=" + ops.get("k2")); // 删除 ops.delete("k1"); System.out.println(JSONObject.toJSONString(ops.entries())); // 迭代 ScanOptions scanOptions = new ScanOptions.ScanOptionsBuilder() .count(5).match("*").build(); Cursor<Map.Entry<String,String>> cursor = ops.scan(scanOptions); while(cursor.hasNext()) { Map.Entry<String,String> entry = cursor.next(); System.out.println(entry.getKey() + "=" + entry.getValue()); }
运行结果:
{"k1":"v1","k2":"100","k3":"v3"} k2=110 {"k2":"110","k3":"v3"} k2=110 k3=v3
BoundListOperations<String,String> ops = redisTemplate.boundListOps("bound-list"); // 新增 ops.leftPush("value1"); ops.rightPush("value2"); ops.rightPush("value1", "value3"); System.out.println(JSONObject.toJSONString(ops.range(0, -1))); // 修改 ops.set(0, "new-" + ops.index(0)); System.out.println(JSONObject.toJSONString(ops.range(0, -1))); // 删除 ops.remove(1, "value2"); System.out.println(JSONObject.toJSONString(ops.range(0, -1)));
运行结果:
["value1","value3","value2"] ["new-value1","value3","value2"] ["new-value1","value3"]
BoundSetOperations<String,String> ops = redisTemplate.boundSetOps("bound-set"); // 新增 ops.add("value1", "value2", "value3", "kval1", "kval2", "kval3", "hval1", "hval2"); System.out.println(JSONObject.toJSONString(ops.members())); // 删除 ops.remove("value2"); System.out.println(JSONObject.toJSONString(ops.members())); // 迭代 ScanOptions scanOptions = new ScanOptions.ScanOptionsBuilder() .count(2).match("kval*").build(); Cursor<String> cursor = ops.scan(scanOptions); while(cursor.hasNext()) { System.out.println(cursor.next()); }
运行结果:
["value3","hval1","kval3","kval1","kval2","hval2","value1","value2"] ["value3","hval1","kval3","kval1","kval2","hval2","value1"] kval3 kval2 kval1
BoundZSetOperations<String,String> ops = redisTemplate.boundZSetOps("bound-zset"); // 新增 ops.add("value1", 1); ops.add("value2", 2); ops.add("value3", 1); ops.add("value4", 3); System.out.println(JSONObject.toJSONString(ops.range(0, -1))); // 删除 ops.remove("value3"); System.out.println(JSONObject.toJSONString(ops.range(0, -1))); // 迭代 ScanOptions scanOptions = new ScanOptions.ScanOptionsBuilder().build(); Cursor<ZSetOperations.TypedTuple<String>> cursor = ops.scan(scanOptions); while(cursor.hasNext()) { ZSetOperations.TypedTuple<String> item = cursor.next(); System.out.println(item.getValue() + " --- " + item.getScore()); }
运行结果:
["value1","value3","value2","value4"] ["value1","value2","value4"] value1 --- 1.0 value2 --- 2.0 value4 --- 3.0
BoundGeoOperations<String,String> ops = redisTemplate.boundGeoOps("bound-geo"); // 成都天府广场坐标 Point point = new Point(104.072206,30.663486); ops.add(point, "chengdu"); // 北京天安门广场坐标 point = new Point(116.403039,39.91513); ops.add(point, "beijing"); // 计算成都到北京的距离 Distance distance = ops.distance("chengdu", "beijing"); System.out.println("相距:" + distance.getValue() + distance.getUnit()); // Metrics.KILOMETERS 公里 // Metrics.MILES 英里 // Metrics.NEUTRAL 米 distance = ops.distance("chengdu", "beijing", Metrics.MILES); System.out.println("相距:" + distance.getValue() + distance.getUnit());
运行结果:
相距:1517797.1972m 相距:943.1178mi