我现在已经尝试了大约一个小时来注册我在我正在制作的游戏中为我的一个课程编写的编解码器。这个班叫做Item
。我尝试了以下3个地方的代码和建议:
这是我提出的代码:
CodecRegistry defaultCodecRegistry = MongoClient.getDefaultCodecRegistry();
MyCodecProvider myCodecProvider = new MyCodecProvider();
ItemCodec itemCodec = new ItemCodec(defaultCodecRegistry);
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(itemCodec), CodecRegistries.fromProviders(myCodecProvider), defaultCodecRegistry);;
MongoClientOptions options = MongoClientOptions.builder().codecRegistry(codecRegistry).build();
client = new MongoClient("localhost:27017", options);
所以我构建了一个名为MyCodecProvider
的编解码器和编解码器提供程序,所以我做错了什么,这怎么会这么复杂?我错过了什么吗?它似乎比它需要的更复杂。如果您需要更多代码,请询问。谢谢。
编辑:我得到的确切错误是org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class [Lnet.hollowbit.archipeloserver.items.Item;.
另外,我试图解析一个Item数组,我是否需要专门为该数组制作一个编解码器?
您可以使用ArrayList为数组执行Mongo编解码器,如下所示:
这是代表订单的类。它包括一个项目的ArrayList。
package com.example.model;
import java.util.ArrayList;
import org.bson.types.ObjectId;
/**
* Class representing an Order.
*/
public class Order
{
private ObjectId id;
private ArrayList<Item> items;
/**
* Default constructor. Needed for testing.
*/
public Order() {
this.items = new ArrayList<>();
}
/**
* Sets the id of the Order.
* @param id The new id of the Order.
*/
public void setId(ObjectId id) {
this.id = id;
}
/**
* Gets the id of the Order.
* @return The id of the Order.
*/
public ObjectId getId() {
return this.id;
}
/**
* Sets the items for the Order.
* @param items The items for the Order.
*/
public void setItems(ArrayList<Item> items) {
this.items = items;
}
/**
* Gets the items for the Order.
* @return The items for the Order.
*/
public ArrayList<Item> getItems() {
return items;
}
/**
* Adds an item to the Order.
* @param item The new Item to add to the Order.
*/
public void addItem(Item item) {
this.items.add(item);
}
}
这是表示订单项的类。订单中可以包含任意数量的商品。项目嵌入在Mongo的订单文档中。
package com.example.model;
import org.bson.types.ObjectId;
/**
* Class representing an order item.
*/
public class Item
{
private ObjectId id;
private String name;
/**
* Constructor.
*/
public Item() {
//
}
/**
* Sets the id of the Item.
* @param id The new id of the Item.
*/
public void setId(ObjectId id) {
this.id = id;
}
/**
* Gets the id of the Item.
* @return The id of the Item.
*/
public ObjectId getId() {
return this.id;
}
/**
* Sets the name of the Item.
* @param name The new name of the Item.
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the name of the Item.
* @return The name of the Item.
*/
public String getName() {
return this.name;
}
}
简单的转换器类,用于将项目转换为文档。
package com.example.mongo;
import com.example.model.Item;
import org.bson.Document;
/**
* Converts Mongo Documents to/from Items.
*/
public class ItemConverter {
/**
* Convert the passed Item into a Mongo Document.
* @param item The Item that you want to convert into a Mongo Document.
* @return Returns the Document that was created from the passed Item.
*/
public Document convert(Item item) {
Document document = new Document();
document.put("_id", item.getId());
document.put("name", item.getName());
return document;
}
/**
* Convert the passed Mongo Document into an Item.
* @param document The Document that you want to convert into an Item.
* @return Returns the Item that was created from the passed Mongo Document.
*/
public Item convert(Document document) {
Item item = new Item();
item.setId(document.getObjectId("_id"));
item.setName(document.getString("name"));
return item;
}
}
用于编码和解码项的编解码器。
package com.example.mongo;
import com.example.model.Item;
import com.mongodb.MongoClient;
import org.bson.BsonReader;
import org.bson.BsonString;
import org.bson.BsonValue;
import org.bson.BsonWriter;
import org.bson.Document;
import org.bson.codecs.Codec;
import org.bson.codecs.CollectibleCodec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.types.ObjectId;
/**
* Mongo Decoder for Items.
*/
public class ItemCodec implements CollectibleCodec<Item> {
private final CodecRegistry registry;
private final Codec<Document> documentCodec;
private final ItemConverter converter;
/**
* Default constructor.
*/
public ItemCodec() {
this.registry = MongoClient.getDefaultCodecRegistry();
this.documentCodec = this.registry.get(Document.class);
this.converter = new ItemConverter();
}
/**
* Codec constructor.
* @param codec The existing codec to use.
*/
public ItemCodec(Codec<Document> codec) {
this.documentCodec = codec;
this.registry = MongoClient.getDefaultCodecRegistry();
this.converter = new ItemConverter();
}
/**
* Registry constructor.
* @param registry The CodecRegistry to use.
*/
public ItemCodec(CodecRegistry registry) {
this.registry = registry;
this.documentCodec = this.registry.get(Document.class);
this.converter = new ItemConverter();
}
/**
* Encode the passed Item into a Mongo/BSON document.
* @param writer The writer to use for encoding.
* @param item The Item to encode.
* @param encoderContext The EncoderContext to use for encoding.
*/
@Override
public void encode(
BsonWriter writer,
Item item,
EncoderContext encoderContext
) {
Document document = this.converter.convert(item);
documentCodec.encode(writer, document, encoderContext);
}
/**
* Get the class that this Codec works with.
* @return Returns the class that this Codec works with.
*/
@Override
public Class<Item> getEncoderClass() {
return Item.class;
}
/**
* Decodes a Mongo/BSON document into an Item.
* @param reader The reader containing the Document.
* @param decoderContext The DecoderContext to use for decoding.
* @return Returns the decoded Item.
*/
@Override
public Item decode(BsonReader reader, DecoderContext decoderContext) {
Document document = documentCodec.decode(reader, decoderContext);
Item item = this.converter.convert(document);
return item;
}
/**
* Generates a new ObjectId for the passed Item (if absent).
* @param item The Item to work with.
* @return Returns the passed Item with a new id added if there
* was none.
*/
@Override
public Item generateIdIfAbsentFromDocument(Item item) {
if (!documentHasId(item)) {
item.setId(new ObjectId());
}
return item;
}
/**
* Returns whether or not the passed Item has an id.
* @param Item The Item that you want to check for
* the presence of an id.
* @return Returns whether or not the passed Item has an id.
*/
@Override
public boolean documentHasId(Item Item) {
return (Item.getName() != null);
}
/**
* Gets the id of the passed Item. If there is no id, it will
* throw an IllegalStateException (RuntimeException).
* @param Item The Item whose id you want to get.
* @return Returns the id of the passed Item as a BsonValue.
*/
@Override
public BsonValue getDocumentId(Item Item)
{
if (!documentHasId(Item)) {
throw new IllegalStateException("The document does not contain an _id");
}
return new BsonString(Item.getName());
}
}
用于编码/解码订单的编解码器。
package com.example.mongo;
import com.example.model.Item;
import com.example.model.Order;
import com.mongodb.MongoClient;
import java.util.ArrayList;
import org.bson.BsonReader;
import org.bson.BsonString;
import org.bson.BsonValue;
import org.bson.BsonWriter;
import org.bson.Document;
import org.bson.codecs.Codec;
import org.bson.codecs.CollectibleCodec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.types.ObjectId;
/**
* Mongo decoder for Orders.
*/
public class OrderCodec implements CollectibleCodec<Order> {
private final CodecRegistry registry;
private final Codec<Document> documentCodec;
private final ItemConverter itemConverter;
/**
* Default constructor.
*/
public OrderCodec() {
this.registry = MongoClient.getDefaultCodecRegistry();
this.documentCodec = this.registry.get(Document.class);
this.itemConverter = new ItemConverter();
}
/**
* Codec constructor.
* @param codec The existing codec to use.
*/
public OrderCodec(Codec<Document> codec) {
this.registry = MongoClient.getDefaultCodecRegistry();
this.documentCodec = codec;
this.itemConverter = new ItemConverter();
}
/**
* Registry constructor.
* @param registry The CodecRegistry to use.
*/
public OrderCodec(CodecRegistry registry) {
this.registry = registry;
this.documentCodec = this.registry.get(Document.class);
this.itemConverter = new ItemConverter();
}
/**
* Encode the passed Order into a Mongo/BSON document.
* @param writer The writer to use for encoding.
* @param order The Order to encode.
* @param encoderContext The EncoderContext to use for encoding.
*/
@Override
public void encode(
BsonWriter writer,
Order order,
EncoderContext encoderContext
) {
Document document = new Document();
document.put("_id", order.getId());
document.put("items", order.getItems());
documentCodec.encode(writer, document, encoderContext);
}
/**
* Get the class that this Codec works with.
* @return Returns the class that this Codec works with.
*/
@Override
public Class<Order> getEncoderClass() {
return Order.class;
}
/**
* Decodes a Mongo/BSON document into an Order.
* @param reader The reader containing the Document.
* @param decoderContext The DecoderContext to use for decoding.
* @return Returns the decoded Order.
*/
@Override
public Order decode(BsonReader reader, DecoderContext decoderContext) {
Document document = documentCodec.decode(reader, decoderContext);
Order order = new Order();
order.setId(document.getObjectId("_id"));
ArrayList<Document> docArr = (ArrayList) document.get("items");
for (Document doc : docArr) {
Item item = this.itemConverter.convert(doc);
order.addItem(item);
}
return order;
}
/**
* Generates a new ObjectId for the passed Order (if absent).
* @param order The Order to work with.
* @return Returns the passed Order with a new id added if there
* was none.
*/
@Override
public Order generateIdIfAbsentFromDocument(Order order) {
if (!documentHasId(order)) {
order.setId(new ObjectId());
}
return order;
}
/**
* Returns whether or not the passed Order has an id.
* @param order The Order that you want to check for
* the presence of an id.
* @return Returns whether or not the passed Order has an id.
*/
@Override
public boolean documentHasId(Order order) {
return (order.getId() != null);
}
/**
* Gets the id of the passed Order. If there is no id, it will
* throw an IllegalStateException (RuntimeException).
* @param order The Order whose id you want to get.
* @return Returns the id of the passed Order as a BsonValue.
*/
@Override
public BsonValue getDocumentId(Order order) {
if (!documentHasId(order)) {
throw new IllegalStateException("The document does not contain an _id");
}
return new BsonString(order.getId().toHexString());
}
}
应用程序的主要类。在这里,我们注册编解码器并创建我们的MongoClient。
package com.example.main;
import com.example.model.Item;
import com.example.model.Order;
import com.example.mongo.ItemCodec;
import com.example.mongo.OrderCodec;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;
import org.bson.Document;
import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
/**
* Main class.
*/
public class Main {
/**
* Main function for the app.
* @param args the command line arguments
*/
public static void main(String[] args) {
CodecRegistry codecRegistry = MongoClient.getDefaultCodecRegistry();
Codec<Document> documentCodec = codecRegistry.get(Document.class);
Codec<Item> itemCodec = new ItemCodec(codecRegistry);
Codec<Order> orderCodec = new OrderCodec(codecRegistry);
codecRegistry = CodecRegistries.fromRegistries(
MongoClient.getDefaultCodecRegistry(),
CodecRegistries.fromCodecs(
documentCodec,
itemCodec,
orderCodec
)
);
MongoClientOptions options = MongoClientOptions.builder().codecRegistry(codecRegistry).build();
MongoClient mongo = new MongoClient(new ServerAddress("localhost", 27018), options);
// Your code here.
}
}
从那里你可以读/写Mongo的订单和物品。