springboot-cache+redis中@CachePut无法正确更新缓存的问题

问题代码:

    @Override
    @CachePut(value = "books",key = "#book.id")
    public Boolean update(Book book) {
        bookDao.updateById(book);
        return bookDao.updateById(book)>0;
    }
    
    @Override
    @Cacheable(value = "books" ,key = "#id")
    public  Book getById(Integer id) {
        Book book= bookDao.selectById(id);
        return  book;
    }

    @Override
    @CacheEvict(value="books",key="#id")
    public Boolean delete(Integer id) {
        return bookDao.deleteById(id)>0;
    }

报错信息:

DBC Connection [com.mysql.cj.jdbc.ConnectionImpl@32958439] will not be managed by Spring
==>  Preparing: UPDATE book SET name=?, type=?, description=? WHERE id=?
==> Parameters: test12(String), test12(String), testtesttesttest12..(String), 44(Integer)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6f794706]
java.lang.ClassCastException: class java.lang.Boolean cannot be cast to class com.zd.domain.Book (java.lang.Boolean is in module java.base of loader 'bootstrap'; com.zd.domain.Book is in unnamed module of loader 'app')
	at com.zd.service.impl.BookNoMPServiceImpl$$EnhancerBySpringCGLIB$$f375a421.getById(<generated>)
	at com.zd.controller.BookController.getById(BookController.java:36)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

分析过程:为类型转化异常,如果不使用修改方法,从Redis缓存取是没有问题的,那么问题出现在修改方法存缓存的过程中。我查看使用修改方法前后Redis缓存存储的对象值,完全不一样。

后又查看下别人写的方法,试着修改如下,就可以了:

 /**
     * 要注意的是@Cacheable注解和@CachePut注解两个方法的返回类型要一致,@CachePut才能生效
     * 也是折磨了很久
     * @param book
     * @return
     */
    @Override
    @CachePut(value = "books",key = "#book.id")
    public Book update(Book book) {
        bookDao.updateById(book);
        return book;
    }

    @Override
    @Cacheable(value = "books" ,key = "#id")
    public  Book getById(Integer id) {
        Book book= bookDao.selectById(id);
        return  book;
    }
@Cacheable注解和@CachePut注解两个方法的返回类型要一致,@CachePut才能生效

@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中,当调用update方法时,该方法体会被执行,并且执行的结果会返回写入到缓存中,所以返回类型必须要一致

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个使用Spring Boot整合Redis的`@Cacheable`、`@CachePut`、`@CacheEvict`注解实现增删改查的示例: 1. 添加Redis依赖 在pom.xml添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> ``` 2. 配置Redis连接 在application.properties添加以下配置: ```properties # Redis连接配置 spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= # 开启缓存 spring.cache.type=redis ``` 3. 编写Redis配置类 ```java import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.lang.reflect.Method; import java.util.Arrays; @Configuration @EnableCaching public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // key序列化方式 RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringRedisSerializer); // key redisTemplate.setHashKeySerializer(stringRedisSerializer); // hash key // value序列化方式 RedisSerializer<Object> valueRedisSerializer = new GenericJackson2JsonRedisSerializer(); redisTemplate.setValueSerializer(valueRedisSerializer); // value redisTemplate.setHashValueSerializer(valueRedisSerializer); // hash value redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory); return builder.build(); } @Bean public KeyGenerator wiselyKeyGenerator() { return (Object target, Method method, Object... params) -> { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); Arrays.stream(params).forEach(param -> sb.append(param.toString())); return sb.toString(); }; } } ``` 4. 编写实体类 ```java import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String name; private Integer age; public User(Integer id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } ``` 5. 编写Service ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private UserDao userDao; @Cacheable(value = "user", keyGenerator = "wiselyKeyGenerator") public User getUserById(Integer id) { return userDao.getUserById(id); } @CachePut(value = "user", keyGenerator = "wiselyKeyGenerator") public User updateUser(User user) { userDao.updateUser(user); return user; } @CacheEvict(value = "user", keyGenerator = "wiselyKeyGenerator") public void deleteUserById(Integer id) { userDao.deleteUserById(id); } } ``` 6. 编写Controller ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/{id}") public User getUserById(@PathVariable Integer id) { return userService.getUserById(id); } @PutMapping("") public User updateUser(@RequestBody User user) { return userService.updateUser(user); } @DeleteMapping("/{id}") public void deleteUserById(@PathVariable Integer id) { userService.deleteUserById(id); } } ``` 7. 测试 启动应用后,可以通过以下方式测试: - 获取用户:GET http://localhost:8080/user/1 - 更新用户:PUT http://localhost:8080/user 请求体: ```json { "id": 1, "name": "Tom", "age": 20 } ``` - 删除用户:DELETE http://localhost:8080/user/1 以上就是一个使用Spring Boot整合Redis的`@Cacheable`、`@CachePut`、`@CacheEvict`注解实现增删改查的示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值