2012-09-12 15 views
5

Moje wyliczenia są przechowywane jako int w mongodb (z aplikacji C#). Teraz w Javie, kiedy próbuję je odzyskać, rzuca wyjątek (wydaje się, że enum można konwertować tylko z wartości ciągu). Czy mogę to zrobić?Spring -Mongodb przechowywanie/pobieranie enums jako int nie string

Również gdy zapiszę niektóre kolekcje do mongodb (z Java), konwertuje wartości wyliczeniowe na ciąg (nie ich wartość/kardynalny). Czy jest dostępne jakieś zastąpienie?

Można to osiągnąć, pisząc konwerter mongodb na poziomie klasy, ale nie chcę pisać konwertera mondodb dla każdej klasy, ponieważ te wyliczenia znajdują się w wielu różnych klasach.

Czy mamy coś na poziomie pola?

Odpowiedz

8

Po długim kopanie w wiosenno-MongoDB kod kalkulator, Ok skończyłem i teraz wszystko działa :) tu jest (jeśli istnieje prostsze rozwiązanie i będzie zadowolony zobaczyć, jak dobrze, to jest co zrobiłem):

najpierw zdefiniować:

public interface IntEnumConvertable { 
     public int getValue();  

}

i prostego wyliczenia, który implementuje to:

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, teraz będzie teraz trzeba 2 konwerterów, jeden jest prosty, druga jest bardziej złożona. ten prosty (to proste dziecko obsługuje również zwykłą konwersję i zwraca ciąg, gdy rzutowanie nie jest możliwe, to jest świetne, jeśli chcesz, aby enum było przechowywane jako łańcuchy znaków i dla wyliczenia, które są liczbami, które mają być przechowywane jako liczby całkowite):

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

tym bardziej skomplikowana, w rzeczywistości jest fabrycznie konwerter:

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

i teraz dla części hack, ja PERSONNALY zrobił znaleźć żadnego „programmitacly” drogę do zarejestrowania zakładu przetwarzającego obrębie mongoConverter, więc wykopany w kodzie i trochę rzucony, oto jest (umieść to 2 funkcje niemowlęcia w twojej klasie @Configuration)

 @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

Dzięki. Użyłem pomysłu na implementację LowerStringToEnumConverter – Demwis

+1

Dziękuję bardzo! To jest bardzo przewodowe, że dane z wiosny nie dają prostego sposobu na zrobienie tego. – ruX

+0

To było całkiem pomocne. –

2

Musisz zaimplementować niestandardowe konwertery i zarejestrować je wiosną.

http://static.springsource.org/spring-data/data-mongo/docs/current/reference/html/#mongo.custom-converters

+0

, które będą działać na poziomie klasy. Nie chcę tego ** już wspomniało o tym w pytaniu – gsagrawal

+0

Nie zauważyłem (sformatuj pytanie, trudno przeczytać) - czy próbowałeś tego. Myślę, że działa również na polach. – gkamal

+2

Inną opcją jest dodanie kolejnego intonującego/ustawiającego dla int do twojego podmiotu dokonującego konwersji. Program pobierający/wyliczający dla wyliczenia powinien być oznaczony jako @Transient. – gkamal

Powiązane problemy