首页 > 解决方案 > 使用 Spring Data 将 io.vavr.collection.Map 存储到 MongoDB

问题描述

我在使用 Spring Data 将序列化和反序列化 vavr 映射到 MongoDB 时遇到问题。

编码

public class Location {
    public final Map<String, String> region;        
    public Location() {
        this.region = HashMap.of("City", "Warsaw", "Country", "Poland");
    }
}

public interface LocationRepository extends CrudRepository<Location, String> {
}

@SpringBootApplication
public class VavrMapMongoApplication {
    public static void main(String[] args) {
        SpringApplication.run(VavrMapMongoApplication.class, args);
    }       
    @Bean
    public CommandLineRunner importData(LocationRepository repository) {
        return (String... args) -> {
            final Location location = new Location();
            repository.save(location);
        };
    }
}

给了我一个例外:

Caused by: java.lang.ClassCastException: class io.vavr.collection.HashMap cannot be cast to class java.util.Map (io.vavr.collection.HashMap is in unnamed module of loader 'app'; java.util.Map is in module java.base of loader 'bootstrap')
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writePropertyInternal(MappingMongoConverter.java:582) ~[spring-data-mongodb-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeProperties(MappingMongoConverter.java:550) ~[spring-data-mongodb-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:526) ~[spring-data-mongodb-2.1.6.RELEASE.jar:2.1.6.RELEASE]

我用@WritingConverterand解决了这个问题@ReadingConverter

@Configuration
public class VavrCustomConverter {
    @Bean
    public MongoCustomConversions customConversions() {
        return new MongoCustomConversions(asList(new VavrMapToMapConverter(), new MapToVavrMapConverter()));
    }

    @WritingConverter
    private static class VavrMapToMapConverter implements Converter<Map, java.util.Map> {
        @Override
        public java.util.Map convert(Map map) {
            return map.toJavaMap();
        }
    }

    @ReadingConverter
    private static class MapToVavrMapConverter implements Converter<java.util.Map, Map> {
        @Override
        public Map convert(java.util.Map map) {
            return HashMap.ofAll(map);
        }
    }
}

但它仅在HashMap包含 java 原始类型时才有效。当我将代码更改为:

public class Region {
    public final String country;
    public final String city;

    public Region(String country, String city) {
        this.country = country;
        this.city = city;
    }
}

public class Location {
    public final Map<String, Region> region;

    public Location(Map<String, Region> region) {
        this.region = region;
    }
}

@Bean
public CommandLineRunner importData(LocationRepository repository) {
    return (String... args) -> {
        final Region region = new Region("Poland", "Warsaw");
        final HashMap<String, Region> pl = HashMap.of("PL", region);
        final Location location = new Location(pl);
        repository.save(location);
}

我有例外:

Caused by: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class test.vavrmapmongo.Region.
    at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46) ~[bson-3.8.2.jar:na]
    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63) ~[bson-3.8.2.jar:na]

为什么?java.util.Map用 POJO 很好地序列化到 MongoDB。我正在寻找使用 vavr Map 的通用方法(不是仅用于Region类的文档转换器)。

标签: javamongodbspring-dataspring-data-mongodbvavr

解决方案


推荐阅读