java - 使用java的mongo驱动程序保存接口(interface)对象列表

标签 java mongodb

我有一个 POJO,它有一个 Resource 列表,它是 ResourceType1ResourceType2 的接口(interface)

public class MyPojo {
 private List<Resource>;
 ....
}

public interface Resource {
  public String getResourceId();
}

public ResourceType1 implements Resource{
  public String getResourceId(){ return resourceType1Id; }
  public String doOtherResourceType1SpecificStuff(){}
}

public ResourceType2 implements Resource{
  public String getResourceId(){ return resourceType2Id; }
  public boolean doOtherResourceType2SpecificStuff(){}
}

public class Database {
  CodecRegistry pojoCodecRegistry = fromRegistries(
            MongoClient.getDefaultCodecRegistry(),
            fromProviders(PojoCodecProvider.builder()
            .register(MyPojo.class)
            .register(ResourceType1.class)
            .register(ResourceType2.class)
            .register(Resource.class)
            .automatic(true).build()));
}

我在数据库类中使用 mongodb-driver-core-3.5.0 来保存和检索 myPojo

我在保存时遇到错误并创建了文档,但当我使用 MongoCompass 检查保存的文档时,资源列表为空。

这是错误:

org.bson.codecs.configuration.CodecConfigurationException: Failed to decode 'resources'. An exception occurred when decoding using the AutomaticPojoCodec.
Decoding into a 'Resource' failed with the following exception:

Cannot find a public constructor for 'Resource'.

A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
at org.bson.codecs.pojo.PojoCodecImpl.decodePropertyModel(PojoCodecImpl.java:173)
at org.bson.codecs.pojo.PojoCodecImpl.decodeProperties(PojoCodecImpl.java:149)
at org.bson.codecs.pojo.PojoCodecImpl.decode(PojoCodecImpl.java:103)
at org.bson.codecs.pojo.PojoCodecImpl.decode(PojoCodecImpl.java:107)
...

我过去也遇到过类似的问题,只是写了一个 MyPojoWrapper 我手动编码和取消编码所有内容。然而我不得不相信这种情况更常见,而且我没有看到一个简单的解决办法。预先感谢您。

最佳答案

public class MongoInterfaceTest {

    private static MongoClient mongoClient;

    static {
        init();
    }

    public static void init() {
        try {
            ClassModel<User> userClassModel = ClassModel.builder(User.class).enableDiscriminator(true).build();
            ClassModel<JavaUser> javaUserClassModel = ClassModel.builder(JavaUser.class).enableDiscriminator(true).build();
            ClassModel<PythonUser> pythonUserClassModel = ClassModel.builder(PythonUser.class).enableDiscriminator(true).build();
            ClassModel<TestUser> testUserClassModel = ClassModel.builder(TestUser.class).enableDiscriminator(true).build();

            CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
                    MongoClientSettings.getDefaultCodecRegistry(),
                    CodecRegistries.fromProviders(
                            PojoCodecProvider.builder()
                                    .register(
                                            userClassModel,
                                            javaUserClassModel,
                                            pythonUserClassModel,
                                            testUserClassModel
                                    )
                                    .automatic(true)
                                    .build()
                    )
            );

            mongoClient = MongoClients.create(
                    MongoClientSettings.builder()
                            .codecRegistry(pojoCodecRegistry)
                            .applyConnectionString(new ConnectionString(ApplictaionConfig.MONGODB_URL))
                            .applyToConnectionPoolSettings(builder -> {
                                builder.minSize(10);
                            })
                            .build()
            );
        } catch (Exception e) {
            System.out.println("Connection mongodb failed");
            throw new RuntimeException();
        }
    }

    public static void main(String[] args) {
        MongoCollection<TestUser> collection = getMongoCollection("TestUser", TestUser.class);

        JavaUser javaUser = new JavaUser("a");
        PythonUser pythonUser = new PythonUser("b","1");

        TestUser testUser = new TestUser(javaUser.name, javaUser);
        insertOne(collection, testUser);

        testUser = new TestUser(pythonUser.name, pythonUser);
        insertOne(collection, testUser);

        Bson bson = Filters.and(Filters.eq("name", "a"));
        TestUser testUser1 = findFirst(collection, bson);
        System.out.println(testUser1);
        System.out.println(testUser1.user.dev());

        bson = Filters.and(Filters.eq("name", "b"));
        testUser1 = findFirst(collection, bson);
        System.out.println(testUser1);
        System.out.println(testUser1.user.dev());
    }

    /**
     * 获得collection对象
     */
    public static <T> MongoCollection<T> getMongoCollection(String collectionName, Class<T> tClass) {
        MongoDatabase mongoDatabase = mongoClient.getDatabase("kikuu");
        MongoCollection<T> collection = mongoDatabase.getCollection(collectionName, tClass);
        return collection;
    }

    public static <T> void insertOne(MongoCollection<T> collection, T document) {
        insertMany(collection, Lists.newArrayList(document));
    }

    public static <T> void insertMany(MongoCollection<T> collection, List<T> documents) {
        collection.insertMany(documents);
    }

    public static <T> T findFirst(MongoCollection<T> collection) {
        return (T) collection.find().first();
    }

    public static <T> T findFirst(MongoCollection<T> collection, Bson bson) {
        return (T) collection.find(bson).first();
    }

    public static interface User {
        String dev();
    }

    public static class JavaUser implements User{
        public String name;

        public JavaUser() {
        }

        public JavaUser(String name) {
            this.name = name;
        }

        @Override
        public String dev() {
            return "java";
        }

        @Override
        public String toString() {
            return "JavaUser{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    public static class PythonUser implements User{
        public String name;
        public String age;

        public PythonUser() {
        }

        public PythonUser(String name, String age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String dev() {
            return "python";
        }

        @Override
        public String toString() {
            return "PythonUser{" +
                    "name='" + name + '\'' +
                    ", age='" + age + '\'' +
                    '}';
        }
    }

    public static class TestUser {
        public String name;
        public User user;

        public TestUser() {
        }

        public TestUser(String name, User user) {
            this.name = name;
            this.user = user;
        }

        @Override
        public String toString() {
            return "TestUser{" +
                    "name='" + name + '\'' +
                    ", user=" + user +
                    '}';
        }
    }
}

关于java - 使用java的mongo驱动程序保存接口(interface)对象列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47800882/

相关文章:

mongodb - 使用 PyMongo,我需要获取另一个集合的字段

mysql - 我应该使用 MongoDB 进行网站电子邮件营销吗?

Java 对象的泛型类型

java - HIbernate:分离父级和所有子级

java - 如何遍历 Object 引用的数组?

javascript - 如何将路由连接到 server.js

date - 如何在Mongodb中按年龄查询?

java - java方法的返回值

java - 使用 JAXB 解码 xml 字符串但得到空字符串

javascript - 类型错误 : Model is not a Constructor