Verwandte Informationen zum verwendeten Federstiefel
Die derzeit verwendete Version von Spring Boot ist 1.5.2.RELEASE
, 数据库操作使用的是 spring-boot-starter-data-jpa
,redis使用的是spring-boot-starter-data-redis
Für Datenbankoperationen verwende ich das von Spring Boot bereitgestellte JPA-Repository und Redis verwendet Redis-Repositorys.
Ein häufiges Szenario besteht darin, Daten über JPA in MySQL zu speichern und nach Erfolg das Hash-Objekt von Redis zu aktualisieren.
Gemäß dem offiziellen Dokument zur Einführung des Spring Data Redis Repositories muss ich die Entität konfigurieren.
2. Verwandte Codes
Nehmen Sie als Beispiel das Speichern einer Bestellung, übergeben Sie ein DTO, rufen Sie die JPA-Methode auf, um in die Datenbank zu schreiben, und schreiben Sie nach Erfolg in den Cache.
Der Hauptcode lautet wie folgt:
Verwenden Sie diese Option, um das Caching in der Hauptdatei zu aktivieren
@EnableRedisRepositories(basePackages = {"com.test"})
@EnableCaching
@SpringBootApplication
@EnableJpaRepositories(basePackages = {"com.test"})
@EnableRedisRepositories(basePackages = {"com.test"})
@EnableCaching
@EnableJpaAuditing
@EntityScan(basePackages = {"com.test"})
@ComponentScan(basePackages = {"com.test"} )
public class Application {
private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
final ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
final String[] activeProfiles = applicationContext.getEnvironment().getActiveProfiles();
for (String profile : activeProfiles) {
LOGGER.info("using profile {}", profile);
}
}
}
RedisConfig schreibt einige Caching-Funktionen neu
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Override
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
System.out.println(sb.toString());
return sb.toString();
}
};
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(300);
return cacheManager;
}
}
OrderService ruft die Speichermethode auf, um die Daten in der Datenbank zu speichern. Dieses Formular wird hier verwendet
@CachePut(value = "order", key = "#order.id")
@Override
public void save(OrderDTO orderDTO) {
try {
Order order = BeanMapper.map(orderDTO, Order.class);
order = orderRepository.save(order);
System.out.println(order);
} catch (Exception e) {
e.printStackTrace();
}
}
@CachePut
注解,生成的key的主键是order:100
Die Einstellungen der Entitäten sind wie folgt. Hier werden sowohl die JPA-Konfiguration als auch die Redis-Konfiguration verwendet. Dies ist etwas vage und ich weiß nicht, ob es korrekt ist.
@Entity
@Table(name = "order")
@RedisHash(value = "order")
public class Order {
private Long id;
private Long userId;
@org.springframework.data.annotation.Id
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Das Hauptproblem, das ich jetzt habe, ist:
1) in
.
Order
实体配置中,如果我在Id
上配置了 redis 的 ID 注解 @org.springframework.data.annotation.Id
, 生成的redis key类似这样 order:1222702657038933405
, 我想要的效果是生成的key直接使用订单id,类似这样 order:100
Ich habe eine Konfiguration für den Dienst
@CachePut(value = "order", key = "#order.id")
2) Beim Debuggen habe ich festgestellt, dass das generierte Objekt, selbst wenn es eine ID hat, immer noch meldet, dass das ID-Attribut des Ausdrucks nicht existiert
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'id' cannot be found on null
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:220) ~[spring-expression-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94) ~[spring-expression-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.expression.spel.ast.PropertyOrFieldReference.accessRrreee0(PropertyOrFieldReference.java:46) ~[spring-expression-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:375) ~[spring-expression-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88) ~[spring-expression-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:120) ~[spring-expression-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:242) ~[spring-expression-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.cache.interceptor.CacheOperationExpressionEvaluator.key(CacheOperationExpressionEvaluator.java:117) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:742) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.generateKey(CacheAspectSupport.java:558) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.collectPutRequests(CacheAspectSupport.java:529) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:413) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:327) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656) ~[spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at com.jiabangou.order.services.impls.OrderServiceImpl$$EnhancerBySpringCGLIB$ceab7f.save(<generated>) ~[classes/:na]
at com.jiabangou.bops.controllers.api.OrderApiController.save(OrderApiController.java:32) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
... 95 common frames omitted
3) Abgesehen von dem Problem, dass der von Redis erstellte Schlüssel falsch ist, haben wir festgestellt, dass das Redis-Objekt erfolgreich gespeichert werden kann, der Datenbankeintrag jedoch nicht erfolgreich erstellt wurde. Wenn Sie die
-Annotation für die Order-Entität entfernen, kann der Datenbankeintrag erfolgreich erstellt werden, der Cache kann jedoch nicht erfolgreich erstellt werden.
首先key应该是属性名
其次@RedisHash在对象持久化到redis中使用,你这里要使用的是redis缓存,不是持久化,所以不关RedisHash什么事。