【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层上使用的。

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,类名及方法名都是对应的。所以想查看这部分使用的,可以直接在项目中查看即可!!

 

相关文章
|
7月前
|
NoSQL Java 网络安全
SpringBoot启动时连接Redis报错:ERR This instance has cluster support disabled - 如何解决?
通过以上步骤一般可以解决由于配置不匹配造成的连接错误。在调试问题时,一定要确保服务端和客户端的Redis配置保持同步一致。这能够确保SpringBoot应用顺利连接到正确配置的Redis服务,无论是单机模式还是集群模式。
631 5
|
7月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
707 2
|
8月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
6769 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
存储 JSON Java
892 0
|
8月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
737 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
7月前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。
764 25
|
7月前
|
缓存 运维 监控
Redis 7.0 高性能缓存架构设计与优化
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Redis 7.0高性能缓存架构,探索函数化编程、多层缓存、集群优化与分片消息系统,用代码在二进制星河中谱写极客诗篇。
1344 3
|
8月前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
344 1
Redis专题-实战篇二-商户查询缓存