找不到我的课程的编解码器(CodecConfigurationException)

时间:2019-08-26 19:46:26

标签: java mongodb codec mongo-java-driver

我需要在mongodb数据库中保存一个Java对象。该对象包含另一个对象。当我尝试保存时,在控制台上收到错误消息:

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class Item.

问题是我为Item类创建了编解码器,但即使将其注册也无法使用。请参阅课程以获取最佳理解。

模型

public class Card(){

  public Card(){
   itens = new ArrayList<Item>()
  }
  String id;
  String description;
  List<Item> itens;
  .
  .
  .

}
public class Item(){

  String id;
  String name; 
  .
  .
  .

}

CardCodec

public class CardCodec implements CollectibleCodec<Card>{
  private final Codec<Document> documentCodec;

  public CardCodec() {      
    this.documentCodec = new DocumentCodec();
  }

  @Override
  public void encode(BsonWriter writer, Card card, EncoderContext encoderContext) {
  Document cardDoc = new Document();
    String id = card.getId();
    String description = card.getDescription();  
    List<Item> itens = card.getItens();

    if(id != null) {
        cardDoc.put("_id", new ObjectId(id));
    }
    if(description != null){
        cardDoc.put("description", card.getDescription);
    }
    if(Itens != null){
        cardDoc.put("itens", card.getItens());
    }
    this.documentCodec.encode(writer, cardDoc, encoderContext);
  }

    @Override
    public Class<Card> getEncoderClass() {      
        return Card.class;
    }

    @Override
    public Card decode(BsonReader reader, DecoderContext decoderContext) {
        Document cardDoc = this.documentCodec.decode(reader, decoderContext);
        Card card=  new Card();

        card.setId(cardDoc .getObjectId("_id").toHexString());
        card.setDescription(cardDoc .getString("description"));

        List<Document> itensDoc =  cardDoc.getList("itens", Document.class);
        List<Item> itens = new ItemConverter().convertToListItem(itensDoc);
        card.setItens(itens);
        return card;
    }

    @Override
    public Card generateIdIfAbsentFromDocument(Card card) {

        if( !documentHasId(card) ) {
        card.setId(new ObjectId().toHexString());
        }

        return card;

    }

    @Override
    public boolean documentHasId(Card card) {       
        return null != card.getId();
    }

    @Override
    public BsonValue getDocumentId(Card card) {
        if(!documentHasId(card)) {
            throw new IllegalStateException("Esse documento não tem um _id");
        }
        return new BsonString(card.getId());
    }

}

转换器

public class ItemConverter {

    public Item convert(Document doc) {
        Item item = new Item();
        String id = doc.getObjectId("_id").toHexString();
        String description = doc.getString("description");
        item.setId(id);
        item.setName(description);
        return item;
    }

    public List<Item> convertToListItem(List<Document> ItensDocs){      
        List<Item> itens = new ArrayList<Item>();   
        if(ItensDocs== null) {
           return Collections.emptyList();
        }
        for(Document doc: ItensDocs) {           
           itens.add( this.convert(doc) );
        }
        return itens;
    }

}

ItemCodec

public class ItemCodec implements CollectibleCodec<Item>{
    private final Codec<Document> documentCodec;

    public ItemCodec() {    
        this.documentCodec = new DocumentCodec();
    }

    @Override
    public void encode(BsonWriter writer, Item value, EncoderContext encoderContext) {
        Document itemDoc = new Document();

        String id = value.getId();
        String name = value.getName();

        if(id != null) {
            itemDoc.put("_id", new ObjectId(id));
        }
        if(name != null) {
            itemDoc.put("name", value.getName());
        }

        documentCodec.encode(writer, itemDoc, encoderContext);
    }

    @Override
    public Class<Item> getEncoderClass() {      
        return Item.class;
    }

    @Override
    public Item decode(BsonReader reader, DecoderContext decoderContext) {      
        Document document = documentCodec.decode(reader, decoderContext);       
        return new ItemConverter().convert(document);
    }

    @Override
    public Item generateIdIfAbsentFromDocument(Item item) {
        if(!this.documentHasId(item)) {
            item.setId(new ObjectId().toHexString());           
        }
        return item;        
    }

    @Override
    public boolean documentHasId(Item item) {       
        return null != item.getId();
    }

    @Override
    public BsonValue getDocumentId(Item item) {
        if(!documentHasId(item)) {
            throw new IllegalStateException("Esse documento não tem um _id");
        }

        return new BsonString(item.getId());

    }


}

现在,我如何注册编解码器

...
    CardCodec cardCodec = new CardCodec();
    ItemCodec itemCodec = new ItemCodec();

    this.codecRegistry = CodecRegistries.fromRegistries(
                MongoClientSettings.getDefaultCodecRegistry(),
                CodecRegistries.fromCodecs(cardCodec, itemCodec)
    );

this.cardCollection = this.mongoDatabase.getCollection("cards", Card.class).withCodecRegistry(this.codecRegistry);
...

当我尝试执行插入操作时:

this.cardCollection.insertOne(card);

我收到:

org.bson.codecs.configuration.CodecConfigurationException

1 个答案:

答案 0 :(得分:0)

手工编写正确且有效的POJO编解码器实现非常棘手。在这种情况下,问题在于您在CardCodec中实例化的DocumentCodec没有配置包含ItemCodec的CodecRegistry,因此无法找到ItemCodec。

有多种方法可以修复编解码器实现,但是我不清楚为什么当驱动程序有一个通用的解决方案时,为什么要自己滚动。有关详细信息,请参见POJO Support

像这样简单地创建您的CodecRegistry:

        CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
            MongoClientSettings.getDefaultCodecRegistry(),
            CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
    );