【问题标题】:MongoDB POJO custom Codecs for nested Classes用于嵌套类的 MongoDB POJO 自定义编解码器
【发布时间】:2020-01-23 14:56:37
【问题描述】:

mongodb-driver-sync 版本 3.8.2

我正在尝试将 Parent 类写入 MongoDB 数据库。

class Parent {

  private Child child;

}

class Child {

  private int a;
  private String b;

}

我想为这两个类提供自定义编解码器并将它们注册到一个中心位置:


 ConnectionString connString = new ConnectionString(connectionString);

 MongoClientSettings settings = MongoClientSettings.builder()
        .applyConnectionString(connString)
        .codecRegistry(
            CodecRegistries.fromRegistries(
                MongoClientSettings.getDefaultCodecRegistry(),
                CodecRegistries.fromCodecs(
                        ////////////////////
                        //// HERE///////////
                        ////////////////////
                     new ParentCodec(), new ChildCodec()
                ))
        ).build();

MongoClient client = MongoClients.create(settings);
........

但是我不知道如何正确实现ParentCodec。我发现的任何示例都是在他们的自定义编解码器中新建一个 DocumentCodec,然后他们使用它来编码他们生成的文档,如下所示:

public class ParentCodec implements Codec<Parent> {

  private Codec<Document> documentCodec = new DocumentCodec();

  @Override
  public void encode(BsonWriter bsonWriter,
                     Parent parent,
                     EncoderContext encoderContext)
  {
    Document doc = new Document();

    doc.put("child", parent.getChild());

    documentCodec.encode(bsonWriter, doc, encoderContext);
  }
}

这会失败,因为新的 DocumentCodec 只知道 DefaultCodecRegistry 中的编解码器:

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class package.Child.
    at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
    at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:184)
    at org.bson.codecs.DocumentCodec.writeIterable(DocumentCodec.java:207)
    at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:180)
    at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:199)
    at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:141)
    at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)

有没有办法解决这个问题?我的意思是,我显然可以这样做:

public class ParentCodec implements Codec<Parent> {

  private Codec<Document> documentCodec = new DocumentCodec(
      CodecRegistries.fromRegistries(
          MongoClientSettings.getDefaultCodecRegistry(),
          CodecRegistries.fromCodecs(
              new ChildCodec()
          )));

但这很难看,我无法在一个中心位置注册所有编解码器。还有什么我错过的吗?

【问题讨论】:

  • 您刚刚新建了 ChildCodec 并在 ParentCodec 中使用它。这就是它对我的工作方式。

标签: java mongodb pojo


【解决方案1】:

将 CodecRegistry 传递给您的编解码器。然后在编解码器中,从注册表中获取 DocumentCodec(使用registry.get(Document.class)),而不是调用new

DocumentCodec 将知道注册表中的所有其他编解码器。

父编解码器

public class ParentCodec implements Codec<Parent> {
    private final CodecRegistry registry;
    private final Codec<Document> documentCodec;

    /**
     * Registry constructor.
     *
     * @param registry The CodecRegistry to use.
     */
    public ParentCodec(CodecRegistry registry) {
        this.registry = registry;
        this.documentCodec = this.registry.get(Document.class);
    }
    // ...
}

主要

public class Main {
    public static void main(String[] args) {
        // ...
        CodecRegistry codecRegistry = MongoClient.getDefaultCodecRegistry();
        codecRegistry = CodecRegistries.fromRegistries(
            CodecRegistries.fromCodecs(new ParentCodec(codecRegistry), new ChildCodec(codecRegistry)),
            codecRegistry
        );
        // ...
    }
}

【讨论】:

    猜你喜欢
    • 2022-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 2019-08-28
    • 2018-06-26
    • 2019-06-13
    • 1970-01-01
    相关资源
    最近更新 更多