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);
}

  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;
} }

【报错】 

启动之后,报错如下: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();
}
};
}

然后在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);
}

然后再去访问一次,

控制台成功从数据库查询了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);
}

具体可以参考:http://www.cnblogs.com/sxdcgaq8080/p/7228163.html查看这几个注解的使用场景

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

本系列的源代码,可以从GitHub上获取查看:https://github.com/AngelSXD/myagenorderdiscount,类名及方法名都是对应的。所以想查看这部分使用的,可以直接在项目中查看即可!!

【redis】5.spring boot项目中,直接在spring data jpa的Repository层使用redis +redis注解@Cacheable直接在Repository层使用,报错问题处理Null key returned for cache operation的更多相关文章

  1. Spring Boot项目中使用Mockito

    本文首发于个人网站:Spring Boot项目中使用Mockito Spring Boot可以和大部分流行的测试框架协同工作:通过Spring JUnit创建单元测试:生成测试数据初始化数据库用于测试 ...

  2. 在Spring Boot项目中使用Spock测试框架

    本文首发于个人网站:在Spring Boot项目中使用Spock测试框架 Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring Boot项目 ...

  3. Spring Boot项目中如何定制拦截器

    本文首发于个人网站:Spring Boot项目中如何定制拦截器 Servlet 过滤器属于Servlet API,和Spring关系不大.除了使用过滤器包装web请求,Spring MVC还提供Han ...

  4. Spring Boot项目中如何定制PropertyEditors

    本文首发于个人网站:Spring Boot项目中如何定制PropertyEditors 在Spring Boot: 定制HTTP消息转换器一文中我们学习了如何配置消息转换器用于HTTP请求和响应数据, ...

  5. Spring Boot项目中如何定制servlet-filters

    本文首发于个人网站:Spring Boot项目中如何定制servlet-filters 在实际的web应用程序中,经常需要在请求(request)外面增加包装用于:记录调用日志.排除有XSS威胁的字符 ...

  6. 你真的理解 Spring Boot 项目中的 parent 吗?

    前面和大伙聊了 Spring Boot 项目的三种创建方式,这三种创建方式,无论是哪一种,创建成功后,pom.xml 坐标文件中都有如下一段引用: <parent> <groupId ...

  7. Spring Boot项目中使用Swagger2

    Swagger2是一款restful接口文档在线生成和在线接口调试工具,Swagger2在Swagger1.x版本的基础上做了些改进,下面是在一个Spring Boot项目中引入Swagger2的简要 ...

  8. 在Spring Boot项目中使用Spock框架

    转载:https://www.jianshu.com/p/f1e354d382cd Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring B ...

  9. Spring Boot2 系列教程(三)理解 Spring Boot 项目中的 parent

    前面和大伙聊了 Spring Boot 项目的三种创建方式,这三种创建方式,无论是哪一种,创建成功后,pom.xml 坐标文件中都有如下一段引用: <parent> <groupId ...

随机推荐

  1. JBuilder生成Exe

    首先保证工程可以通过绿箭头执行 然后在File菜单中选择New,先建立Archive下的Application 接下来的界面中大部分可以直接选择“Next”,除了下面的第3步,会询问是否需要将工程引用 ...

  2. Selenium WebDriver-判断页面中某一元素是否可操作

    driver.get("http://127.0.0.1/test_enable.html") i1=driver.find_element_by_id("input1& ...

  3. python学习-- 在for循环中还有很多有用的东西,如下:

    变量 描述 forloop.counter 索引从 1 开始算 forloop.counter0 索引从 0 开始算 forloop.revcounter 索引从最大长度到 1 forloop.rev ...

  4. SDOJ 2605 闲荡

    描述 L 饭后无聊,便在 BugTown 里闲荡. BugTown 共有 N 栋房屋和 M 条有向道路.每栋房屋都有一个非负整数 vi 作为标识. BugTown 有一个特性十分神奇:从任意一个房屋离 ...

  5. A Few Laughing Men

    A Few Laughing Men CodeChef - LAUGHMEN Balaji is a great person to hang out with. He tells really am ...

  6. MySQL可供选择的存储引擎

    备注:以下关于5.7版本的内容是来源于官方文档:https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html 以下关于5.6版本的内容,一部 ...

  7. PTA 11-散列1 电话聊天狂人 (25分)

    题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/722 5-14 电话聊天狂人   (25分) 给定大量手机用户通话记录,找出其中通话次数 ...

  8. RHEL 7.3修改网卡命名规则为ethX

    RHEL 7网卡默认命名规则:以太网卡(Ethernet)为enX,无线网卡(WLAN)为wlX,修改网卡命名规则为ethX如下: 1.修改/etc/sysconfig/grub文件,添加net.if ...

  9. Linux Shell系列教程之(二)第一个Shell脚本

    本文是Linux Shell系列教程的第(二)篇,更多shell教程请看:Linux Shell系列教程 通过上一篇教程的学习,相信大家已经能够对shell建立起一个大体的印象了,接下来,我们通过一个 ...

  10. Linux 终端操作之「I/O Redirection」

    I/O 重定向是在终端运行程序时很常用的技巧,但是我对它所知甚少.今天我在 DigitalOcean 上发现了一篇很好的 tutorial.这篇随笔记录一下我的心得体会和发现的一个问题. I/O re ...