问题代码:
@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方法时,该方法体会被执行,并且执行的结果会返回写入到缓存中,所以返回类型必须要一致。