我需要在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
答案 0 :(得分:0)
手工编写正确且有效的POJO编解码器实现非常棘手。在这种情况下,问题在于您在CardCodec中实例化的DocumentCodec没有配置包含ItemCodec的CodecRegistry,因此无法找到ItemCodec。
有多种方法可以修复编解码器实现,但是我不清楚为什么当驱动程序有一个通用的解决方案时,为什么要自己滚动。有关详细信息,请参见POJO Support。
像这样简单地创建您的CodecRegistry:
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
MongoClientSettings.getDefaultCodecRegistry(),
CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
);