Java的Redis和RedisTemplate的相關(guān)操作

一.什么是Redis

Redis是一個(gè)非關(guān)系型數(shù)據(jù)庫,具有很高的存取性能,一般用作緩存數(shù)據(jù)庫,減少正常存儲數(shù)據(jù)庫的壓力。

Redis可以存儲鍵與5種不同數(shù)據(jù)結(jié)構(gòu)類型之間的映射,這5種數(shù)據(jù)結(jié)構(gòu)類型分別為String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。

下面來對這5種數(shù)據(jù)結(jié)構(gòu)類型作簡單的介紹:
image.png

二.RedisTemplate及其相關(guān)方法

  • 1.RedisTemplate

Spring封裝了RedisTemplate對象來進(jìn)行對Redis的各種操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各種操作、異常處理及序列化,支持發(fā)布訂閱,并對spring 3.1 cache進(jìn)行了實(shí)現(xiàn)。RedisTemplate提供了redis各種操作、異常處理及序列化,支持發(fā)布訂閱,并對spring 3.1 cache進(jìn)行了實(shí)現(xiàn)。RedisTemplate提供了redis各種操作、異常處理及序列化,支持發(fā)布訂閱,并對spring 3.1 cache進(jìn)行了實(shí)現(xiàn)。RedisTemplate提供了redis各種操作、異常處理及序列化,支持發(fā)布訂閱,并對spring 3.1 cache進(jìn)行了實(shí)現(xiàn)。


image.png

注意 RedisTemplate是一個(gè)key和value都是泛型的模板類,一般情況下key為String類型,如:RedisTemplate<String,Object>。

此外,如果沒特殊情況,切勿定義成RedisTemplate<Object, Object>,否則根據(jù)里氏替換原則,使用的時(shí)候會造成類型錯(cuò)誤 。

spring-data-redis針對jedis提供了如下功能:
1.連接池自動(dòng)管理,提供了一個(gè)高度封裝的“RedisTemplate”類
2.針對jedis客戶端中大量api進(jìn)行了歸類封裝,將同一類型操作封裝為operation接口
ValueOperations:簡單K-V操作

       SetOperations:set類型數(shù)據(jù)操作

       ZSetOperations:zset類型數(shù)據(jù)操作

       HashOperations:針對map類型的數(shù)據(jù)操作

       ListOperations:針對list類型的數(shù)據(jù)操作

2.RedisTemplate中定義了對5種數(shù)據(jù)結(jié)構(gòu)操作

redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set

opsForXXX和boundXXXOps的區(qū)別?

XXX為value的類型,前者獲取一個(gè)operator,但是沒有指定操作的對象(key),可以在一個(gè)連接(事務(wù))內(nèi)操作多個(gè)key以及對應(yīng)的value;后者獲取了一個(gè)指定操作對象(key)的operator,在一個(gè)連接(事務(wù))內(nèi)只能操作這個(gè)key對應(yīng)的value。

關(guān)于計(jì)數(shù)的API(increment)有一個(gè)bug,需要各位使用中注意,通過increment計(jì)數(shù)以后,通過get方式獲取計(jì)數(shù)值的時(shí)候可能會拋出EOF異常(和本地的jdk以及redis的編譯版本有關(guān)),可以考慮使用boundValueOps(key).get(0,-1)獲取計(jì)數(shù)值。

三.RedisTemplate操作Redis數(shù)據(jù)庫的具體例子
1.值類型操作:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/applicationContext-redis.xml")
public class TestValue {
    @Autowired
    private RedisTemplate redisTemplate;    
    @Test
    public void setValue(){
//存值,針對值類型,ops相當(dāng)于options
        redisTemplate.boundValueOps("name").set("itcast");      
    }   
    @Test
    public void getValue(){
        String str = (String) redisTemplate.boundValueOps("name").get();
        System.out.println(str);
    }   
    @Test
    public void deleteValue(){
        redisTemplate.delete("name");
    }   
}

2.集合類型操作之Set類型,無序,即存取順序不一定相同

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/applicationContext-redis.xml")
public class TestSet {
     
    @Autowired
    private RedisTemplate redisTemplate;
     
    /**
     * 存入值
     */
    @Test
    public void setValue(){
        redisTemplate.boundSetOps("nameset").add("曹操");     
        redisTemplate.boundSetOps("nameset").add("劉備"); 
        redisTemplate.boundSetOps("nameset").add("孫權(quán)");
    }
     
    /**
     * 提取值
     */
    @Test
    public void getValue(){
        Set members = redisTemplate.boundSetOps("nameset").members();
        System.out.println(members);
    }
     
    /**
     * 刪除集合中的某一個(gè)值
     */
    @Test
    public void deleteValue(){
        redisTemplate.boundSetOps("nameset").remove("孫權(quán)");
    }
     
    /**
     * 刪除整個(gè)集合
     */
    @Test
    public void deleteAllValue(){
        redisTemplate.delete("nameset");
    }
}

輸出結(jié)果:[孫權(quán), 劉備, 曹操],此外,set類型的元素也不可重復(fù)。當(dāng)set沒有值的時(shí)候,會返回一個(gè)[]
3.List類型操作

list類型分為兩種,一種是左壓棧,一種是右壓棧

右壓棧:

/**
 * 右壓棧:后添加的對象排在后邊,相當(dāng)于隊(duì)列,相當(dāng)于先進(jìn)先出
 */
@Test
public void testSetValue1(){        
    redisTemplate.boundListOps("namelist1").rightPush("劉備");
    redisTemplate.boundListOps("namelist1").rightPush("關(guān)羽");
    redisTemplate.boundListOps("namelist1").rightPush("張飛");        
}
 
/**
 * 顯示右壓棧集合,range 表示查詢的索引,從第幾個(gè)查到第幾個(gè),如果想查詢所有的數(shù)的話只能將第二個(gè)數(shù)寫得大一點(diǎn)。
 */
@Test
public void testGetValue1(){
    List list = redisTemplate.boundListOps("namelist1").range(0, 10);
    System.out.println(list);
}

運(yùn)行結(jié)果:[劉備, 關(guān)羽, 張飛],元素可以重復(fù)

左壓棧:

/**
 * 左壓棧:后添加的對象排在前邊,相當(dāng)于棧,先進(jìn)后出
 */
@Test
public void testSetValue2(){        
    redisTemplate.boundListOps("namelist2").leftPush("劉備");
    redisTemplate.boundListOps("namelist2").leftPush("關(guān)羽");
    redisTemplate.boundListOps("namelist2").leftPush("張飛");     
}
 
/**
 * 顯示左壓棧集合
 */
@Test
public void testGetValue2(){
    List list = redisTemplate.boundListOps("namelist2").range(0, 10);
    System.out.println(list);
}

運(yùn)行結(jié)果:[張飛, 關(guān)羽, 劉備]

根據(jù)索引查詢元素

/**
 * 查詢集合某個(gè)元素
 */
@Test
public void testSearchByIndex(){
    String s = (String) redisTemplate.boundListOps("namelist1").index(1);
    System.out.println(s);
}

運(yùn)行結(jié)果:返回索引為1的元素移除某個(gè)元素的值

/**
 * 移除集合某個(gè)元素,其中remove中第一個(gè)參數(shù)是移除的個(gè)數(shù)
 */
@Test
public void testRemoveByIndex(){
    redisTemplate.boundListOps("namelist1").remove(1, "關(guān)羽");
}

這里表示移除一個(gè)“關(guān)羽”。

4.Hash類型操作

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/applicationContext-redis.xml")
public class TestHash {
  @Autowired
  private RedisTemplate redisTemplate;
  
  //  存值
  @Test
  public void testSetValue() {
    redisTemplate.boundHashOps("namehash").put("a", "唐僧");
    redisTemplate.boundHashOps("namehash").put("b", "悟空");
    redisTemplate.boundHashOps("namehash").put("c", "八戒");
    redisTemplate.boundHashOps("namehash").put("d", "沙僧");
  }
  
  //獲取所有的key
  @Test
  public void testGetKeys() {
    Set s = redisTemplate.boundHashOps("namehash").keys();
    System.out.println(s);
  }
  
  //  獲取所有的value
  @Test
  public void testGetValues() {
    List values = redisTemplate.boundHashOps("namehash").values();
    System.out.println(values);
  }
  
  //  根據(jù)key獲取值
  @Test
  public void testGetValueByKey() {
    Object object = redisTemplate.boundHashOps("namehash").get("b");
    System.out.println(object);
  }
  
  //根據(jù)key移除值
  @Test
  public void testRemoveValueByKey() {
    redisTemplate.boundHashOps("namehash").delete("c");
  }
  
}

四.RedisTemplate和StringRedisTemplate的區(qū)別

  1. 兩者的關(guān)系是StringRedisTemplate繼承RedisTemplate。

  2. 兩者的數(shù)據(jù)是不共通的;也就是說StringRedisTemplate只能管理StringRedisTemplate里面的數(shù)據(jù),RedisTemplate只能管理RedisTemplate中的數(shù)據(jù)。

  3. SDR默認(rèn)采用的序列化策略有兩種,一種是String的序列化策略,一種是JDK的序列化策略。

StringRedisTemplate默認(rèn)采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。

RedisTemplate默認(rèn)采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

RedisTemplate使用的序列類在在操作數(shù)據(jù)的時(shí)候,比如說存入數(shù)據(jù)會將數(shù)據(jù)先序列化成字節(jié)數(shù)組然后在存入Redis數(shù)據(jù)庫,這個(gè)時(shí)候打開Redis查看的時(shí)候,你會看到你的數(shù)據(jù)不是以可讀的形式展現(xiàn)的,而是以字節(jié)數(shù)組顯示,類似下面


image.png

當(dāng)然從Redis獲取數(shù)據(jù)的時(shí)候也會默認(rèn)將數(shù)據(jù)當(dāng)做字節(jié)數(shù)組轉(zhuǎn)化,這樣就會導(dǎo)致一個(gè)問題,當(dāng)需要獲取的數(shù)據(jù)不是以字節(jié)數(shù)組存在redis當(dāng)中而是正常的可讀的字符串的時(shí)候,比如說下面這種形式的數(shù)據(jù)

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容