java - Spring Data Reactive Mongo:类类型转换器
问题描述
我正在使用带有反应式 mongo 存储库的 Spring boot 2 webflux。我正在尝试持久化和查询具有Class<>
字段类型的实体。但我不知道如何配置我的应用程序以使用这种类型。这是我想存储在 mongo 中的实体:
import lombok.Data;
import org.springframework.data.annotation.Id;
@Data
public class ServiceEntity {
@Id
private String id;
private String name;
private Class inputClass;
}
这是我的 mongo 配置:
import static java.util.Arrays.asList;
import com.mongodb.MongoClient;
import com.mongodb.MongoException;
import com.mongodb.async.client.MongoClientSettings;
import lombok.extern.slf4j.Slf4j;
import org.bson.BsonReader;
import org.bson.BsonWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecProvider;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
@Configuration
@Slf4j
public class MongoConfiguration {
@Bean
public MongoClientSettings settings() {
log.debug("Configure mongo settings");
return MongoClientSettings.builder()
.codecRegistry(CodecRegistries.fromRegistries(
CodecRegistries.fromProviders(new ClassCodecProvider()),
MongoClient.getDefaultCodecRegistry()))
.build();
}
// @Bean
public MongoCustomConversions customConversions() {
log.debug("Configure mongo custom conversions");
return new MongoCustomConversions(asList(new StringToClassConverter()));
}
private static class ClassCodec implements Codec<Class> {
@Override
public Class decode(BsonReader reader, DecoderContext decoderContext) {
try {
return Class.forName(reader.readString());
} catch (ClassNotFoundException e) {
throw new MongoException("Couldn't read value as class type", e);
}
}
@Override
public void encode(BsonWriter writer, Class value, EncoderContext encoderContext) {
writer.writeString(value.getName());
}
@Override
public Class<Class> getEncoderClass() {
return Class.class;
}
}
private static class ClassCodecProvider implements CodecProvider {
@Override
public <T> Codec<T> get(Class<T> clazz, CodecRegistry registry) {
if (clazz == Class.class) {
return (Codec<T>) new ClassCodec();
}
return null;
}
}
private static class StringToClassConverter implements Converter<String, Class> {
@Override
public Class convert(String source) {
try {
return Class.forName(source);
} catch (ClassNotFoundException e) {
throw new MongoException("Couldn't read string as class type", e);
}
}
}
}
问题是当我尝试从 mongo 读取实体时出现错误:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.lang.Class<?>]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleRead(MappingMongoConverter.java:887)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1392)
我还创建了字符串到类转换器(请参阅StringToClassConverter
配置)并尝试将其用作自定义转换器。@Bean
但是当我将这样的配置放到上下文中(在方法上做取消注释注释customConversions()
)时,它已被用于任何字符串转换。结果,在保存实体时:
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Class<?>] for value 'service1'; nested exception is com.mongodb.MongoException: Couldn't read string as class type
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:46)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleWrite(MappingMongoConverter.java:849)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeSimpleInternal(MappingMongoConverter.java:829)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeProperties(MappingMongoConverter.java:488)
完整代码可在github上找到。请参阅com.example.mongoclasspertist.ServiceRepositoryTest#test
重现。
通过将PR提交到Spring 存储库,我看到了如何解决这个问题的下一个方法(但它们可能会导致另一个问题)ClassToStringConverter
:StringToClassConverter
org.springframework.data.mongodb.core.convert.MongoConverters
org.springframework.data.mongodb.core.convert.MappingMongoConverter#getPotentiallyConvertedSimpleWrite
请帮我解决这个问题。
解决方案
在转换器上使用注释@ReadingConverter
似乎可以完成这项工作。请试一试。
@ReadingConverter
private static class StringToClassConverter implements Converter<String, Class>
{
推荐阅读
- php - 无法检索数字输入并将其分配给变量
- python - 在 Pandas 中应用 IF 条件 - 结果变量
- python - 如何使用 Python 在 Outlook 中发送 HTML 格式的电子邮件?
- r - 如何在 R 中测量 mlr3 模型的性能?
- python - 我的代码通过 python shell 工作,但不是终端
- ansible - Packer.io - 拨打 tcp 172.XXX:22:连接:没有到主机的路由
- css - HighCharts如何在加载饼图时删除显示
- javascript - debounce函数是幂等的吗?
- python - Pygame以全屏开始然后崩溃
- python - 不和谐.py | 如何向我的机器人所在的每个公会的所有者发送消息