Sau một thời gian dài đào mã bộ chuyển đổi spring-mongodb, tôi đã hoàn thành và bây giờ nó đang hoạt động :) đây rồi (nếu có giải pháp đơn giản hơn, tôi cũng sẽ rất vui khi thấy, đây là những gì tôi đã làm):
đầu tiên xác định:
public interface IntEnumConvertable {
public int getValue();
}
và một enum đơn giản thực hiện nó:
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, bây giờ bạn sẽ cần 2 bộ chuyển đổi, một bộ đơn giản, bộ kia phức tạp hơn. cái đơn giản (con đơn giản này cũng đang xử lý chuyển đổi đơn giản và trả về một chuỗi khi không thể ép kiểu, điều đó thật tuyệt nếu bạn muốn lưu trữ enum dưới dạng chuỗi và đối với enum là số được lưu trữ dưới dạng số nguyên):
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();
}
}
}
}
phức tạp hơn, thực sự là một nhà máy chuyển đổi:
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;
}
}
}
và bây giờ đối với phần hack, tôi người phân tích không tìm thấy bất kỳ cách "lập trình" nào để đăng ký nhà máy chuyển đổi trong mongoConverter, vì vậy tôi đã đào mã và với một chút đúc, đây là nó (đặt 2 chức năng trẻ em này vào @Configuration của bạn lớp)
@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;
}