2012-09-12 15 views
5

Mis enums se almacenan como int en mongodb (desde la aplicación C#). Ahora en Java, cuando trato de recuperarlos, arroja una excepción (parece que enum solo se puede convertir desde el valor de cadena). ¿Hay alguna manera de que pueda hacerlo?Spring -Mongodb almacenamiento/recuperación de enums como int no string

También cuando guardo algunas colecciones en mongodb (de Java), convierte los valores enum a cadena (no su valor/cardinal). ¿Hay alguna anulación disponible?

Esto se puede lograr escribiendo mongodb-converter en el nivel de clase, pero no quiero escribir mondodb-converter para cada clase, ya que estas enumeraciones se encuentran en muchas clases diferentes.

¿Tenemos algo en el campo?

Respuesta

8

Después de un largo excavación en el código convertidor de primavera-mongodb, Ok i terminado y ahora se está trabajando :) aquí está (si no es la solución más simple seré feliz veo así, esto es lo que he hecho):

primero definir:

public interface IntEnumConvertable { 
     public int getValue();  

}

y una enumeración simple que implementa que:

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, ahora que ahora se necesitan 2 convertidores, uno es simple, el otro es más complejo. el simple (este bebé simple también está manejando el simple convertir y devuelve una cadena cuando el molde no es posible, eso es genial si quieres tener enum almacenado como cadenas y para enum que son números que se almacenarán como enteros):

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

cuanto más complejo es uno, es en realidad una fábrica convertidor:

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

y ahora viene la parte hack, i personnaly dio encontrar ninguna manera "programmitacly" para registrar una fábrica convertidor dentro de un mongoConverter, así que excavado en el código y con un poco de fundición, aquí está (ponga estas 2 funciones de bebés en su clase @Configuration)

+1

Gracias. Usé una idea para implementar LowerStringToEnumConverter – Demwis

+1

¡Muchas gracias! Está muy conectado que los datos de primavera no proporcionan una forma simple de hacerlo – ruX

+0

Esto fue bastante útil. –

2

Deberá implementar sus conversores personalizados y registrarlos con la primavera.

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

+0

que funcionará a nivel de clase ... no quiero que ** ya lo mencioné en la pregunta – gsagrawal

+0

No lo note (formatee su pregunta por favor, difícil de leer) - lo intentó. Creo que también funciona para los campos. – gkamal

+2

La otra opción es agregar otro getter/setter para ints a su entidad que realiza la conversión. El getter/setter para enum debe marcarse como @Transient. – gkamal