sql >> Databasteknik >  >> NoSQL >> MongoDB

Spring -Mongodb lagrar/hämtar enums som int inte sträng

Efter ett långt grävande i vår-mongodb-omvandlarkoden, ok, jag är klar och nu fungerar den :) här är den (om det finns en enklare lösning kommer jag gärna se också, det här är vad jag har gjort) :

först definiera :

public interface IntEnumConvertable {
      public int getValue();    
}

och en enkel uppräkning som implementerar det:

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;
    }
}

Ok, nu kommer du att behöva två omvandlare, den ena är enkel, den andra är mer komplex. den enkla (denna enkla baby hanterar också den enkla omvandlingen och returnerar en sträng när cast inte är möjligt, det är bra om du vill ha enum som lagras som strängar och för enum som är tal som ska lagras som heltal) :

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();
            }               
        }
    }   
 }

den mer komplexa, är faktiskt en omvandlarfabrik:

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;   
            }
        }
}

och nu när det gäller hackdelen så hittade jag personligen inget "programmässigt" sätt att registrera en omvandlarfabrik i en mongoConverter, så jag grävde i koden och med lite casting, här är den (lägg in dessa 2 babyfunktioner i din @Configuration klass)

      @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;
    } 


  1. hur man hittar distinkta fält av en modell på en och tillstånd i mangust?

  2. Att göra en hel modell skrivskyddad med Mongoid

  3. Skicka filer från Amazon S3 genom NodeJS-servern utan att exponera S3 URL?

  4. Plattning mongoDB-schema