有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

MongoDB:注册编解码器(Java)

我已经试了大约一个小时来注册一个编解码器,我为我的一个班级制作了一个我正在制作的游戏。该类称为Item。我从以下三个地方尝试了代码和建议:

下面是我的代码:

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;.另外,我正在尝试解析一个项目数组,我是否也需要专门为该数组制作一个编解码器


共 (2) 个答案

  1. # 1 楼答案

    更好的方法是实现您自己的codeprovider。通过这种方式,您可以管理所有使用的编解码器实现。使用您的案例:

    创建mycodeprovider

    public class MyCodecProvider implements CodecProvider {
    
    private final BsonTypeClassMap bsonTypeClassMap;
    
    public MyCodecProvider(final BsonTypeClassMap bsonTypeClassMap) {
        this.bsonTypeClassMap = bsonTypeClassMap;
    }
    
    @Override
    public <T> Codec<T> get(final Class<T> clazz, final CodecRegistry registry) {
        if (clazz == Document.class) {
            // construct DocumentCodec with a CodecRegistry and a BsonTypeClassMap
            return (Codec<T>) new org.bson.codecs.DocumentCodec(registry, bsonTypeClassMap);
        }
        else if (clazz == Order.class) {
            return (Codec<T>) new OrderCodec(registry);
        }
        else if (clazz == Item.class) {
            return (Codec<T>) new ItemCodec(registry);
        }
    
        return null;
      }
    }
    

    现在你可以在你的主课上简单地做这个

    Map<BsonType, Class<?>> replacements = new HashMap<BsonType, Class<?>>();
        replacements.put(BsonType.DATE_TIME, Timestamp.class);
    

    //替换。put(BsonType.DATE\u TIME,Timestamp.class);如果您有复杂的java类型

        BsonTypeClassMap bsonTypeClassMap = new BsonTypeClassMap(replacements);
    
    
        MyCodecProvider provider = new MyCodecProvider(bsonTypeClassMap);
        CodecRegistry pojoCodecRegistry = fromRegistries(MongoClient.getDefaultCodecRegistry(),
                fromProviders(PojoCodecProvider.builder().automatic(true).build()));
        CodecRegistry codecRegistry = MongoClient.getDefaultCodecRegistry();
        Codec<Document> documentCodec = codecRegistry.get(Document.class);
    
        codecRegistry = CodecRegistries.fromRegistries(
                CodecRegistries.fromProviders(provider),
                CodecRegistries.fromRegistries(pojoCodecRegistry),
                CodecRegistries.fromCodecs(documentCodec));
    
        MongoClientOptions options = MongoClientOptions.builder().codecRegistry(codecRegistry).build();
        MongoClient mongo = new MongoClient(new ServerAddress("localhost", 27018), options);
    
  2. # 2 楼答案

    您可以使用ArrayList对阵列执行Mongo编解码器,如下所示:

    com。实例模型命令

    这是表示订单的类。它包括项目的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);
        }
    }
    

    com。实例模型项目

    这是表示订单项的类。订单中可以有任意数量的项目。项目嵌入到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;
        }
    }
    

    com。实例蒙戈。项目转换器

    将项目转换为文档或从文档转换为项目的简单转换器类

    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;
        }
    }
    

    com。实例蒙戈。项目编码解码器

    用于对项目进行编码和解码的编解码器

    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());
        }
    
    }
    

    com。实例蒙戈。编解码器

    用于编码/解码顺序的编解码器

    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());
        }
    }
    

    com。实例主要的主要

    应用程序的主类。在这里,我们注册编解码器并创建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读/写订单和商品