我使用Spring Data Redis用Spring Boot 2.0例。在此示例中,我试图将客户数据+学生数据保存在一起。我不太确定这里的数据建模如何发生,但是假设它与Mongo DB(纯非关系)相同。
Spring Data Redis
Spring Boot 2.0
有人可以帮忙解决以下错误吗?很明显,期望进行一些转换才能看到数据。
错误:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.javasampleapproach.redis.model.Customer] to type [java.lang.String] at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174) at org.springframework.data.redis.serializer.GenericToStringSerializer$Converter.convert(GenericToStringSerializer.java:120) at org.springframework.data.redis.serializer.GenericToStringSerializer.serialize(GenericToStringSerializer.java:88) at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:184) at org.springframework.data.redis.core.DefaultHashOperations.put(DefaultHashOperations.java:175) at com.javasampleapproach.redis.repository.CustomerRepositoryImpl.save(CustomerRepositoryImpl.java:33) at com.javasampleapproach.redis.repository.CustomerRepositoryImpl$$FastClassBySpringCGLIB$$88e26a2c.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) at com.javasampleapproach.redis.repository.CustomerRepositoryImpl$$EnhancerBySpringCGLIB$$7d20fd4e.save(<generated>) at com.javasampleapproach.controller.WebController.save(WebController.java:31) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Unknown Source)
RedisConfig.java
@Configuration @ComponentScan("com.javasampleapproach.*") public class RedisConfig { @Bean public JedisConnectionFactory jedisConnectionFactory() { return new JedisConnectionFactory(); } @Bean public RedisTemplate<String, Object> redisTemplate(){ final RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(jedisConnectionFactory()); template.setKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericToStringSerializer<Object>(Object.class)); template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class)); return template; } }
Controller.java
@RequestMapping("/save") public String save() { List<Student> students = new ArrayList<>(); Student student = Student.builder().firstName("John").build(); students.add(student); customerRepository.save(Customer.builder().id(1).firstName("Jack").lastName("Smith").students(students).build()); return "Done"; }
CustomerRepositoryImpl.java
@Repository public class CustomerRepositoryImpl implements CustomerRepository { private static final String KEY = "Customer"; private RedisTemplate<String, Object> redisTemplate; private HashOperations<String, Long, Customer> hashOperations; @Autowired public CustomerRepositoryImpl(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } @PostConstruct private void init() { hashOperations = redisTemplate.opsForHash(); } @Override public void save(Customer customer) { hashOperations.put(KEY, customer.getId(), customer); } @Override public Customer find(Long id) { return hashOperations.get(KEY, id); } @Override public Map<Long, Customer> findAll() { return hashOperations.entries(KEY); } @Override public void update(Customer customer) { hashOperations.put(KEY, customer.getId(), customer); } @Override public void delete(Long id) { hashOperations.delete(KEY, id); } }
pom.xml
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
在保留对象之前,应该使用序列化程序。请参阅Spring Data Redis文档的这一部分:
可以通过在Redis中使用各种数据结构来存储数据。Jackson2JsonRedisSerializer可以转换JSON格式的对象。理想情况下,可以使用纯键将JSON存储为值。您可以使用Redis哈希来实现结构化对象的更复杂映射。Spring Data Redis提供了各种将数据映射到哈希的策略(取决于用例): 通过使用HashOperations和序列化器进行直接映射 使用Redis仓库 使用HashMapper和HashOperations
可以通过在Redis中使用各种数据结构来存储数据。Jackson2JsonRedisSerializer可以转换JSON格式的对象。理想情况下,可以使用纯键将JSON存储为值。您可以使用Redis哈希来实现结构化对象的更复杂映射。Spring Data Redis提供了各种将数据映射到哈希的策略(取决于用例):
编辑:
将您GenericToStringSerializer的RedisTemplatebean定义替换为JdkSerializationRedisSerializer(默认的序列化程序)或Jackson2JsonRedisSerializer或GenericJackson2JsonRedisSerializer以JSON格式序列化。
GenericToStringSerializer
RedisTemplate
JdkSerializationRedisSerializer
Jackson2JsonRedisSerializer
GenericJackson2JsonRedisSerializer