Spring-Mongodb将枚举存储/检索为int而不是string
我的枚举在mongodb中存储为int(来自C#app)。现在在Java中,当我试图检索它们时,它抛出一个异常(似乎枚举只能从字符串值转换)。我有什么办法可以做吗 另外,当我将一些集合保存到mongodb(来自Java)时,它会将枚举值转换为字符串(而不是它们的值/基数)。是否有可用的覆盖 这可以通过在类级别编写mongodb转换器来实现,但我不想为每个类编写mondodb转换器,因为这些枚举位于许多不同的类中Spring-Mongodb将枚举存储/检索为int而不是string,spring,mongodb,spring-mongo,Spring,Mongodb,Spring Mongo,我的枚举在mongodb中存储为int(来自C#app)。现在在Java中,当我试图检索它们时,它抛出一个异常(似乎枚举只能从字符串值转换)。我有什么办法可以做吗 另外,当我将一些集合保存到mongodb(来自Java)时,它会将枚举值转换为字符串(而不是它们的值/基数)。是否有可用的覆盖 这可以通过在类级别编写mongodb转换器来实现,但我不想为每个类编写mondodb转换器,因为这些枚举位于许多不同的类中 那么,我们在字段级别上有什么吗?您需要实现自定义转换器,并向spring注册它 在长
那么,我们在字段级别上有什么吗?您需要实现自定义转换器,并向spring注册它
在长时间挖掘spring mongodb转换器代码后, 好的,我完成了,现在它工作了:)在这里(如果有更简单的解决方案,我也很乐意看到,这就是我所做的): 首先定义:
public interface IntEnumConvertable {
public int getValue();
}
以及实现它的简单枚举:
public enum tester implements IntEnumConvertable{
vali(0),secondvali(1),thirdvali(5);
private final int val;
private tester(int num)
{
val = num;
}
public int getValue(){
return val;
}
}
好的,现在你需要2个转换器,一个很简单,
另一个更复杂。简单的一个(这个简单的婴儿也在处理简单的转换,当无法进行强制转换时返回一个字符串,如果您希望将enum存储为字符串,并且对于将数字存储为整数的enum,这非常好):
公共类整数转换器{
@写转换器
公共静态类EnumToIntegerConverter实现Converter enumType=targetType;
while(enumType!=null&&!enumType.isEnum()){
enumType=enumType.getSuperclass();
}
if(enumType==null){
抛出新的IllegalArgumentException(
“目标类型”+targetType.getName()+“未引用枚举”);
}
返回新的IntegerToEnum(枚举类型);
}
@读取转换器
公共静态类IntegerToEnum实现转换器{
私有最终类枚举类型;
公共IntegerToEnum(类enumType){
this.enumType=enumType;
}
@凌驾
公共枚举转换(整数源){
对于(T:enumType.getEnumConstants()){
if(可转换意向的t实例)
{
if(((IntEnumConvertable)t).getValue()==source.intValue()){
返回t;
}
}
}
返回null;
}
}
}
现在对于hack部分,我个人没有找到任何“programmitacly”方法在mongoConverter中注册转换器工厂,所以我在代码中进行了挖掘,并进行了一些转换,就是这样(将这两个婴儿函数放在@Configuration类中)
@Bean
公共CustomConversions CustomConversions(){
列表>();
添加(新的IntegerEnumConverters.EnumToIntegerConverter());
//这是一个虚拟注册,实际上是一个解决方案,因为
//spring mongodb没有注册转换器工厂的选项。
//所以我们注册了我们工厂使用的转换器。
add(新的IntegerToEnumConverterFactory.IntegerToEnum(null));
返回新的自定义转换(转换器);
}
@豆子
公共映射MongoConverter MappingMongoConverter()引发异常{
MongoMappingContext mappingContext=新建MongoMappingContext();
mappingContext.setApplicationContext(appContext);
DbRefResolver DbRefResolver=新的默认DbRefResolver(mongoDbFactory());
MappingMongoConverter mongoConverter=新的MappingMongoConverter(dbRefResolver,mappingContext);
setCustomConversions(customConversions());
ConversionService convService=mongoConverter.getConversionService();
((GenericConversionService)convService).addConverterFactory(新的IntegerToEnumConverterFactory());
mongoConverter.AfterPropertieSet();
返回mongoConverter;
}
这将在课堂上起作用。。我不希望**在问题中已经提到了这一点,但没有注意到(请格式化你的问题,很难阅读)-你试过了吗。我认为它也适用于字段。另一个选项是向进行转换的实体中添加另一个int的getter/setter。枚举的getter/setter应标记为@Transient。它将第一个输入作为类。所以它不是泛型的,对于每个枚举/类,我必须添加一个转换器。u给出的另一个选项很好,但这是一种解决方法。上面的回执对我来说并不顺利,因为Spring Mongo开始应用给定的转换器将Integer
类型的所有查询值转换为Enum
,在我的例子中,这样就导致了所有整型值的null
s。为了解决这个问题,我必须将@ReadingConverter
放在转换器工厂(因此将其从IntegerToEnum
转换器中删除)。
public class IntegerEnumConverters {
@WritingConverter
public static class EnumToIntegerConverter implements Converter<Enum<?>, Object> {
@Override
public Object convert(Enum<?> source) {
if(source instanceof IntEnumConvertable)
{
return ((IntEnumConvertable)(source)).getValue();
}
else
{
return source.name();
}
}
}
}
public class IntegerToEnumConverterFactory implements ConverterFactory<Integer, Enum> {
@Override
public <T extends Enum> Converter<Integer, T> getConverter(Class<T> targetType) {
Class<?> enumType = targetType;
while (enumType != null && !enumType.isEnum()) {
enumType = enumType.getSuperclass();
}
if (enumType == null) {
throw new IllegalArgumentException(
"The target type " + targetType.getName() + " does not refer to an enum");
}
return new IntegerToEnum(enumType);
}
@ReadingConverter
public static class IntegerToEnum<T extends Enum> implements Converter<Integer, Enum> {
private final Class<T> enumType;
public IntegerToEnum(Class<T> enumType) {
this.enumType = enumType;
}
@Override
public Enum convert(Integer source) {
for(T t : enumType.getEnumConstants()) {
if(t instanceof IntEnumConvertable)
{
if(((IntEnumConvertable)t).getValue() == source.intValue()) {
return t;
}
}
}
return null;
}
}
}
@Bean
public CustomConversions customConversions() {
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(new IntegerEnumConverters.EnumToIntegerConverter());
// this is a dummy registration , actually it's a work-around because
// spring-mongodb doesnt has the option to reg converter factory.
// so we reg the converter that our factory uses.
converters.add(new IntegerToEnumConverterFactory.IntegerToEnum(null));
return new CustomConversions(converters);
}
@Bean
public MappingMongoConverter mappingMongoConverter() throws Exception {
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.setApplicationContext(appContext);
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mappingContext);
mongoConverter.setCustomConversions(customConversions());
ConversionService convService = mongoConverter.getConversionService();
((GenericConversionService)convService).addConverterFactory(new IntegerToEnumConverterFactory());
mongoConverter.afterPropertiesSet();
return mongoConverter;
}