sql >> Database >  >> NoSQL >> MongoDB

Spring -Mongodb die opsommingen opslaat/ophaalt als int niet string

Na lang graven in de lente-mongodb-convertercode, ok, ik ben klaar en nu werkt het :) hier is het (als er een eenvoudigere oplossing is, zal ik dat ook graag zien, dit is wat ik heb gedaan):

definieer eerst :

public interface IntEnumConvertable {
      public int getValue();    
}

en een eenvoudige opsomming die het implementeert:

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 heb je 2 converters nodig, de ene is eenvoudig, de andere is complexer. de eenvoudige (deze eenvoudige baby behandelt ook de eenvoudige conversie en retourneert een string wanneer casten niet mogelijk is, dat is geweldig als je enum wilt hebben opgeslagen als strings en voor enum die getallen zijn die moeten worden opgeslagen als gehele getallen) :

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

de meer complexe is eigenlijk een converterfabriek:

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

en nu voor het hackgedeelte, ik heb persoonlijk geen "programmamatige" manier gevonden om een ​​converterfabriek binnen een mongoConverter te registreren, dus ik heb de code ingegraven en met een beetje casten, hier is het (zet deze 2 baby's-functies in je @Configuration klas)

      @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. gem-install van mongoid gooit een niet-geïnitialiseerde constante in Ruby, werkt in irb

  2. Mongodump gebruiken voor 1 verzameling

  3. Zoeken naar object in Mongoose Sub Array

  4. Welke database te kiezen (Cassandra, MongoDB, ?) voor het opslaan en opvragen van gebeurtenis- / log- / metrische gegevens?