【redis】5.spring boot項目中,直接在spring data jpa的Repository層使用redis +redis注解@Cacheable直接在Repository層使用,報錯問題處理Null key returned for cache operation


spring boot整合redis:http://www.cnblogs.com/sxdcgaq8080/p/8028970.html

首先,明確一下問題的場景

之前在spring boot整合redis,關於redis的使用都是在repository層上再封裝一層service層,在service層上使用的。

現在如果直接將redis的注解放在repository上使用,是個什么情況呢?

代碼如下:

  1.首先我有一個實體XxAdmin,主鍵為id

  2.Xxadmin我寫了一個AdminRepository

package com.agen.myagen.repository;


import com.agen.myagen.entity.XxAdmin;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaRepository;


/**
 * admin持久化層
 *
 * @author SXD
 * @date 2017/12/26
 */
public interface AdminRepository extends JpaRepository<XxAdmin,Integer> {

    /**
     * 查找機構信息
     * 並緩存到redis,鍵為id  值為XxAdmin
     * @param adminId
     * @return
     */
    @Cacheable(value="admins", key="#adminId")
    @Override
    XxAdmin findOne(Integer adminId);
}
View Code

  3.我在controller直接調用

package com.agen.controller;


import com.agen.myagen.entity.XxAdmin;
import com.agen.myagen.repository.AdminRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;


@Controller
public class MainController {

    @Resource
    private AdminRepository adminRepository;

    @RequestMapping("index")
    public String getOrder(String adminId){
        Integer adminID = Integer.parseInt(adminId);
        XxAdmin admin = adminRepository.findOne(adminID);
        return  null;
    }


}
View Code

 

【報錯】 

啟動之后,報錯如下:Null key returned for cache operation (maybe you are using named params on classes without debug info?)

java.lang.IllegalArgumentException: Null key returned for cache operation (maybe you are using named params on classes without debug info?) Builder[public abstract com.agen.myagen.entity.XxAdmin com.agen.myagen.repository.AdminRepository.findOne(java.lang.Integer)] caches=[admins] | key='#adminId' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'

報這個錯,原因就是redis認定這個key是Null的,沒辦法存入,所以報錯了。

 

但是之前咱們上一篇就是這么用的呀,查看上一篇,可以發現,redis是使用在service層,是在repository的再封裝層使用的,那redis就不能直接使用在repository層了么?

【這里因為項目原因,不贅述為什么不封裝一層service層使用,而是直接在repository層使用】【最后具體為什么key在這里會認定為null也沒有找到原因,若知情,懇請告知!!!謝謝了】

 

【解決方法】

翻來覆去之后,發現redis的@Cacheable注解放在repository方法上,key會被認定為null,導致存不進redis緩存。

所以,換一種思路來解決這個問題,就是提前設定一種key的生成策略,即在RedisConfig類中指定一種KeyGenerator。【這一步驟的解釋,可以查看http://www.cnblogs.com/sxdcgaq8080/p/8028970.html

具體的解決方法如下:

  在RedisConfig中,設定僅取第一個參數作為key的key生成策略

/**
     * 生成key的策略【自定義第三種】
     * 使用范圍:僅適用於選取第一個參數做鍵的情況
     * 由於reposotory上不能直接使用spel表達式作key,故而采用key的生成策略的方式來替換
     *
     * 使用時在注解@Cacheable(value = "admins",keyGenerator = "firstParamKeyGenerator")中指定
     * @return
     */
    @Bean(name = "firstParamKeyGenerator")
    public KeyGenerator firstParamKeyGenerator(){
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(params[0].toString());
                return sb.toString();
            }
        };
    }
View Code

然后在AdminRepository中更換@Cacheable中的屬性

public interface AdminRepository extends JpaRepository<XxAdmin,Integer> {

    /**
     * 查找機構信息
     * 並緩存到redis,鍵為id  值為XxAdmin
     * @param adminId
     * @return
     */
    @Cacheable(value="admins", keyGenerator = "firstParamKeyGenerator")
    @Override
    XxAdmin findOne(Integer adminId);
}
View Code

 

然后再去訪問一次,

控制台成功從數據庫查詢了Xxadmin對象

查看redis中,已經將本對象存入緩存

 

 

再次訪問,發現並未執行SQL語句,直接從緩存中取出本對象。

OK,直接在spring boot的repository層使用redis注解成功。

==============================================================================================================================================

最后,可以將AdminRepository類上使用

@CacheConfig(cacheNames = "admins")

指定本類中所有的方法,操作的緩存都是名為admins的緩存!!

package com.agen.myagen.repository;


import com.agen.myagen.entity.XxAdmin;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaRepository;


/**
 * admin持久化層
 *
 * @author SXD
 * @date 2017/12/26
 */
@CacheConfig(cacheNames = "admins")
public interface AdminRepository extends JpaRepository<XxAdmin,Integer> {

    /**
     * 查找機構信息
     * 並緩存到redis,鍵為id  值為XxAdmin
     * @param adminId
     * @return
     */
    @Cacheable(keyGenerator = "firstParamKeyGenerator")
    @Override
    XxAdmin findOne(Integer adminId);
}
View Code

 

具體可以參考:http://www.cnblogs.com/sxdcgaq8080/p/7228163.html查看這幾個注解的使用場景

 

==============================================================================================================================================

本系列的源代碼,可以從GitHub上獲取查看:https://github.com/AngelSXD/myagenorderdiscount,類名及方法名都是對應的。所以想查看這部分使用的,可以直接在項目中查看即可!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM