【问题标题】:Dynamic POJO type with MongoDB Java collection带有 MongoDB Java 集合的动态 POJO 类型
【发布时间】:2019-08-13 18:16:04
【问题描述】:

我了解如何使用 MongoDB Java 驱动程序来读取和存储 POJO 的我们知道我们正在使用的特定类型。在我正在处理的项目中,编解码器提供程序(以及编解码器注册表)是由通过属性传入的类名构建的(有一些硬编码值)。这支持例如仅在进行测试(JUnit)时注销某些消息。

问题是我无法确定如何使用 MongoCollection 使用这种类型。下面是一个基于实际问题的玩具问题(我们有一个通用的“消息”接口,我们希望记录的所有 POJO 都实现该接口。日志记录函数接受该“消息”接口的对象并需要将其插入集合)。

首先我们有我们的界面:

public interface MyInterface {
    int getX();
}

简单的实现:

public class ImplA implements MyInterface {
    public int getX(){return 1;}
}

然后是使用它们的代码:

import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import org.bson.codecs.pojo.ClassModel;
import org.bson.codecs.pojo.PojoCodecProvider;

import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;

public class Main {

    public static void main(String[] args){
        new Main().run();
    }

    public void run(){
        MongoClient client = MongoClients.create("mongodb://localhost:27018");
        MongoDatabase db = client.getDatabase("db1").withCodecRegistry(fromRegistries(
                MongoClientSettings.getDefaultCodecRegistry(),
                fromProviders(PojoCodecProvider.builder().register(
                        ClassModel.builder(MyInterface.class).enableDiscriminator(true).build(),
                        ClassModel.builder(ImplA.class).enableDiscriminator(true).build()
                ).build())
        ));

        MyInterface obj1 = new ImplA();

        db.getCollection("ImplA",ImplA.class).insertOne((ImplA) obj1);
        db.getCollection("ImplA",obj1.getClass()).insertOne(obj1);
        db.getCollection("ImplA",Object.class).insertOne(obj1);
    }
}

当第一个插入编译时,第二个失败并出现此错误:

Error:Error:line (42)java: 不兼容的类型:Main.MyInterface 不能转换为 capture#1 of ?扩展 Main.MyInterface

在我看来这个功能应该是可能的,因为 MongoCollection 肯定有关于类型的信息。传入的对象具有某种类型,我想要该类型的集合并插入它。如果第二个 insertOne 被注释掉,则代码编译。驱动程序抛出一个异常,说 Object 没有编解码器;因此,它肯定是从给定的集合中确定要使用的编解码器。

更新:我曾尝试使用 getClass.cast 进行各种强制转换,各种泛型组合,但这里有一个可行的选项:

MyInterface obj1 = new ImplA();

Class<MyInterface> myC = (Class<MyInterface>) Class.forName(obj1.getClass().getName());
db.getCollection("ImplA",myC).insertOne(obj1);

这会引发类未找到异常,并且看起来不必要地复杂。

【问题讨论】:

    标签: java mongodb generics pojo mongodb-java


    【解决方案1】:

    尝试使用:db.getCollection("ImplA").withDocumentClass(obj1.getClass()).insertOne(obj1)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-24
      • 2018-12-28
      • 2021-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多