Spring -Mongodb将枚举存储/检索为int而不是字符串 [英] Spring -Mongodb storing/retrieving enums as int not string
问题描述
我的枚举以int形式存储在mongodb中(来自C#应用程序).现在在Java中,当我尝试检索它们时,它将引发异常(似乎只能从字符串值转换为enum).我有什么办法吗?
My enums are stored as int in mongodb (from C# app). Now in Java, when I try to retrieve them, it throws an exception (it seems enum can be converted from string value only). Is there any way I can do it?
另外,当我将一些集合保存到mongodb(来自Java)中时,它会将枚举值转换为字符串(而不是其值/基数).是否有任何覆盖?
Also when I save some collections into mongodb (from Java), it converts enum values to string (not their value/cardinal). Is there any override available?
这可以通过在类级别上编写mongodb-converter来实现,但是我不想为每个类编写mondodb-converter,因为这些枚举在许多不同的类中.
This can be achieved by writing mongodb-converter on class level but I don't want to write mondodb-converter for each class as these enums are in many different classes.
那么我们在现场有什么东西吗?
So do we have something on the field level?
推荐答案
在对spring-mongodb转换器代码进行了长时间的挖掘之后, 好的,我完成了,现在可以正常工作了:)在这里(如果有更简单的解决方案,我也很高兴看到,这就是我所做的):
After a long digging in the spring-mongodb converter code, Ok i finished and now it's working :) here it is (if there is simpler solution i will be happy see as well, this is what i've done ) :
首先定义:
public interface IntEnumConvertable {
public int getValue();
}
和一个实现它的简单枚举:
and a simple enum that implements it :
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个转换器,一个很简单, 另一个比较复杂.简单的方法(这个简单的方法也可以处理简单的转换,并在无法进行强制转换时返回一个字符串,如果您希望将枚举存储为字符串并且将枚举数字存储为整数,则非常有用):>
Ok, now you will now need 2 converters , one is simple , the other is more complex. the simple one (this simple baby is also handling the simple convert and returns a string when cast is not possible, that is great if you want to have enum stored as strings and for enum that are numbers to be stored as integers) :
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();
}
}
}
}
更复杂的一个实际上是转换器工厂:
the more complex one , is actually a converter factory :
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;
}
}
}
现在对于hack部分,我个人没有找到任何编程方式"在mongoConverter中注册转换器工厂,因此我在代码中进行了一点点铸造,在这里(将这2个婴儿函数放在您的@Configuration类)
and now for the hack part , i personnaly didnt find any "programmitacly" way to register a converter factory within a mongoConverter , so i digged in the code and with a little casting , here it is (put this 2 babies functions in your @Configuration class)
@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;
}
这篇关于Spring -Mongodb将枚举存储/检索为int而不是字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!