spring-使用 CustomEntityMapper 时读取时未填充数据弹性 Id 字段
spring-data-elastic Id field not populated on reads when using CustomEntityMapper
弹性版本 - 1.7.6
spring启动 - 1.3.5
使用 spring-data-elasticsearch 我已经按照其他地方的建议创建了一个自定义 JSON 映射,以支持 Java8 新的日期时间字段。
这工作正常 - 但由于不再填充 id 字段,因此会中断从存储库中读取实体。
自定义配置:
@Bean
@Autowired
public ElasticsearchTemplate elasticsearchTemplate(Client client) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
return new ElasticsearchTemplate(client, new CustomEntityMapper(objectMapper));
}
public class CustomEntityMapper implements EntityMapper {
private ObjectMapper objectMapper;
public CustomEntityMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
}
@Override
public String mapToString(Object object) throws IOException {
return objectMapper.writeValueAsString(object);
}
@Override
public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
return objectMapper.readValue(source, clazz);
}
}
示例实体:
@Document(indexName = "scanner", type = "Entry")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Entry {
@Id
private String id;
@Field(type= FieldType.String)
private String path;
@Field(type = FieldType.Date, format = DateFormat.date_time )
private OffsetDateTime created;
}
注意 - 当我删除 CustomEntityMapper 时,将返回 id 字段。我追踪了 spring-data-elasticsearch 代码,
并确定它无法从 DefaultResultMapper.setPersistentId 中的弹性响应中解析 Id 字段,因为
mappingContext 为空。
private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) {
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
PersistentProperty<ElasticsearchPersistentProperty> idProperty = mappingContext.getPersistentEntity(clazz).getIdProperty();
// Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
Method setter = idProperty.getSetter();
if (setter != null) {
try {
setter.invoke(result, id);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
}
有人遇到过这个问题吗?如何在不破坏 Id 分辨率的情况下支持 CustomEntityMapper?
升级到 spring 启动 1.4.1-RELEASE 解决了问题
弹性版本 - 1.7.6 spring启动 - 1.3.5
使用 spring-data-elasticsearch 我已经按照其他地方的建议创建了一个自定义 JSON 映射,以支持 Java8 新的日期时间字段。 这工作正常 - 但由于不再填充 id 字段,因此会中断从存储库中读取实体。
自定义配置:
@Bean
@Autowired
public ElasticsearchTemplate elasticsearchTemplate(Client client) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
return new ElasticsearchTemplate(client, new CustomEntityMapper(objectMapper));
}
public class CustomEntityMapper implements EntityMapper {
private ObjectMapper objectMapper;
public CustomEntityMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
}
@Override
public String mapToString(Object object) throws IOException {
return objectMapper.writeValueAsString(object);
}
@Override
public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
return objectMapper.readValue(source, clazz);
}
}
示例实体:
@Document(indexName = "scanner", type = "Entry")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Entry {
@Id
private String id;
@Field(type= FieldType.String)
private String path;
@Field(type = FieldType.Date, format = DateFormat.date_time )
private OffsetDateTime created;
}
注意 - 当我删除 CustomEntityMapper 时,将返回 id 字段。我追踪了 spring-data-elasticsearch 代码, 并确定它无法从 DefaultResultMapper.setPersistentId 中的弹性响应中解析 Id 字段,因为 mappingContext 为空。
private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) {
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
PersistentProperty<ElasticsearchPersistentProperty> idProperty = mappingContext.getPersistentEntity(clazz).getIdProperty();
// Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
Method setter = idProperty.getSetter();
if (setter != null) {
try {
setter.invoke(result, id);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
}
有人遇到过这个问题吗?如何在不破坏 Id 分辨率的情况下支持 CustomEntityMapper?
升级到 spring 启动 1.4.1-RELEASE 解决了问题