Spring JPA 中的懒惰集合与 Jackson 和 elasticsearch whtout jsonignore



我们有带有 elasticsearch 和 mysql 的 spring boot。我们有一个功能,可以将 mysql 中的所有数据重新索引到 elasticsearch 中,它很简单:

@Service
@Transactional
public class SearchIndexer {
public void reindex(){
elasticsearchRepository.save(jpaRepository.findAll());
}
}

现在我们有一个名为 invoice 的实体,它有一个带有"派生"计算的延迟加载集合:

@Entity
@Table(name = "invoice")
@Document(indexName = "invoice")
public class Invoice implements Serializable {
//... other props
@OneToMany(fetch = FetchType.LAZY, mappedBy = "invoice")
@JsonIgnore
private Set<InvoiceItem> invoiceItems = new LinkedHashSet<>();
// getter and setters for invoiceItems
public boolean isAllSimple() {
if(getInvoiceType()==null){
return false;
}
if(getInvoiceItems()==null){
return false;
}
for(InvoiceItem item : getInvoiceItems()){
if(!item.isSimple()){
return false;
}
}
return true;
}
}

当使用rest控制器时,生成的json正确包含属性"allSimple"。这是因为我们在一个事务中使用hibernate5module运行它。

但是,当我们调用elasticsearchRepository.save(jpaRepository.findAll())(也在事务中(时,elasticsearch 的对象映射器无法序列化 "allSimple" 属性,因为LazyInitializationException.弹性搜索对象映射器的配置如下:

@Bean
public ElasticsearchTemplate elasticsearchTemplate(Client client, Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder, Hibernate5Module hibernate5Module) {       
return new ElasticsearchTemplate(client, new CustomEntityMapper(jackson2ObjectMapperBuilder.createXmlMapper(false).modulesToInstall(hibernate5Module).build()));        
}
public class CustomEntityMapper implements EntityMapper {
private ObjectMapper objectMapper;
public CustomEntityMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;    
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);
}
}

hibernate5module 已加载并注册,但未解决问题。 通常我们会向该属性添加"JsonIgnore",但我们需要该值,因此这不是选项。 有什么想法吗?!

我有一个用这个配置的项目。

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "com.sagasoftware.tracker.*")
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
Hibernate5Module hibernate5Module = new Hibernate5Module();
objectMapper.registerModule(hibernate5Module);
objectMapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
messageConverter.setObjectMapper(objectMapper);
return messageConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(mappingJackson2HttpMessageConverter());
super.configureMessageConverters(converters);
}
}

如果您使用的是 Spring boot,则声明 bean MappingJackson2HttpMessageConverter 并注册 hibernate5module 应该可以解决您的问题。

我可以通过 rest 控制器渲染实体。

最新更新