spring-data-elasticsearch版本为4.0.0
es版本为7.6.2
项目中需要将es5.4.3升级为7.4.1。由于两个版本的差异很大,升级需要升级jar包,重写api。但在升级过程中遇到一个问题。
当java中某字段如下配置时
image.png
当使用ElasticsearchRestTemplate.update(updateQuery, indexCoordinates);保存数据时,如果某时间为1970-01-01 08:00:00时,其保存到es后,会存储为0。展示如下
image.png
这时使用ElasticsearchRestTemplate.search(searchQuery, clazz);时会报错,报错信息如下
image.png
从报错信息来看,缺少Integer->Date的转换器,导致转换失败。
既然spring缺少转换器,那我们添加自定义转换器不就可以解决这个问题了吗?
添加转换器如下
import org.springframework.core.convert.converter.Converter;
import java.util.Date;
public class IntegerDateConverter implements Converter<Integer, Date> {
@Override
public Date convert(Integer source) {
if (source == null) {
return null;
}
return new Date(source);
}
}
转换器注册如下
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters" >
<set>
<bean class="com.test.web.convert.util.IntegerDateConverter"/>
</set>
</property>
</bean>
<mvc:annotation-driven conversion-service="conversionService"/>
然后重启项目进行测试....
然后悲剧的发现,还是不行.....
查看spring-data-elasticsearch源码,发现如下
org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter
image.png
看到这里基本就明白问什么我们添加自定义类型转换器后不生效了。因为我们的类型转换器注册到了spring容器,但是他并没用使用spring容器中的Bean,所以压根获取不到我们新添加的转换器。不得不说,这里真是坑.....
源码中的DefaultConversionService代码如下,可以看出器只添加了部分常用的类型转换器。
package org.springframework.core.convert.support;
import java.nio.charset.Charset;
import java.util.Currency;
import java.util.Locale;
import java.util.UUID;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.lang.Nullable;
public class DefaultConversionService extends GenericConversionService {
@Nullable
private static volatile DefaultConversionService sharedInstance;
public DefaultConversionService() {
addDefaultConverters(this);
}
public static ConversionService getSharedInstance() {
DefaultConversionService cs = sharedInstance;
if (cs == null) {
synchronized (DefaultConversionService.class) {
cs = sharedInstance;
if (cs == null) {
cs = new DefaultConversionService();
sharedInstance = cs;
}
}
}
return cs;
}
public static void addDefaultConverters(ConverterRegistry converterRegistry) {
addScalarConverters(converterRegistry);
addCollectionConverters(converterRegistry);
converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new StringToTimeZoneConverter());
converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());
converterRegistry.addConverter(new ObjectToObjectConverter());
converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new FallbackObjectToStringConverter());
converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
}
public static void addCollectionConverters(ConverterRegistry converterRegistry) {
ConversionService conversionService = (ConversionService) converterRegistry;
converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
converterRegistry.addConverter(new MapToMapConverter(conversionService));
converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
converterRegistry.addConverter(new StringToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
converterRegistry.addConverter(new StringToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));
converterRegistry.addConverter(new StreamConverter(conversionService));
}
private static void addScalarConverters(ConverterRegistry converterRegistry) {
converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());
converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCharacterConverter());
converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new NumberToCharacterConverter());
converterRegistry.addConverterFactory(new CharacterToNumberFactory());
converterRegistry.addConverter(new StringToBooleanConverter());
converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));
converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new StringToLocaleConverter());
converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCharsetConverter());
converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCurrencyConverter());
converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToPropertiesConverter());
converterRegistry.addConverter(new PropertiesToStringConverter());
converterRegistry.addConverter(new StringToUUIDConverter());
converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
}
}
查看源码org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions
发现其又添加了一些自定义类型转换器,那我们是不是也可以在这里补充一下类型转化器是不是就解决问题了?我们试试
在项目中创建一个包org.springframework.data.elasticsearch.core.convert。然后拷贝源码中的类org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions到该包下。并添加我们自己的代码
结构如下
ElasticsearchCustomConversions类中添加代码如下
image.png
然后在此类的最前面注册此转换器
image.png
由于我们重写了源码中的类,且包名类名都与源码相同。根据tomcat类加载策略,优先加载用户自定义的类,所以我们自定义的类会生效,详细原理参考文章:https://www.cnblogs.com/aspirant/p/8991830.html
重启项目,测试,发现问题解决......
网友评论