我们有springsearch和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-controller时,生成的json正确包含属性“allSimple”。这是因为我们在一个事务中使用hibernate5module运行它。
但是,当我们调用elasticsearchRepository.save(jpaRepository.findAll())
时(也在事务中),弹性搜索的objectmapper无法序列化“allSimple”属性,因为LazyInitializationException
。 elasticsearch-objectmapper配置如下:
@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”,但我们需要该值,所以这不是选项。 有什么想法吗?!
答案 0 :(得分:0)
我有一个用这个配置的项目。
@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应该可以解决你的问题。
我可以通过休息控制器渲染一个实体。