【问题标题】:MongoDB getCollection with a specific document class具有特定文档类的 MongoDB getCollection
【发布时间】:2023-03-16 01:20:01
【问题描述】:

我的问题是将MongoDB 文档转换为一种类型:

getCollectionjavadoc 说:

  /**
     * Gets a collection, with a specific default document class.
     *
     * @param collectionName the name of the collection to return
     * @param documentClass  the default class to cast any documents returned from the database into.
     * @param <TDocument>    the type of the class to use instead of {@code Document}.
     * @return the collection
     */
    <TDocument> MongoCollection<TDocument> getCollection(String collectionName, Class<TDocument> documentClass);

这是我的实现:

public class AccountDAO {

    public static FindIterable<AccountDTO> accountPersist(AccountDTO accountDTO){
        MongoCollection<AccountDTO> accountDataCollection = Utils.getDbCollection();
        accountDataCollection.insertOne(accountDTO);
        return accountDataCollection.find();
    }
}

还有getDbCollection

public static MongoCollection<AccountDTO>  getDbCollection() {
        MongoDatabase db = Utils.getDbConnect();
        MongoCollection<AccountDTO> accountDataCollection = null ;
        accountDataCollection = db.getCollection(AccountDTO.COLLECTION_NAME,AccountDTO.class);
        return accountDataCollection;
    }

CodecImplementationProvider:

package utils;

import org.bson.BsonReader;
import org.bson.BsonWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecRegistry;

import digester.Account;
import digester.Customer;
import dto.AccountDTO;

// the Codec extends two interfaces: Encoder<T>, Decoder<T>
class MyAccountDTOImpCodec implements Codec<AccountDTO> {

    private CodecRegistry codecRegistry;

    public MyAccountDTOImpCodec(CodecRegistry codecRegistry) {
        this.codecRegistry = codecRegistry;
    }

    public void encode(BsonWriter writer, AccountDTO doc, EncoderContext encoderContext) {
        writer.writeStartDocument();
        writer.writeName("IBAN");
        writer.writeString(doc.getIBAN());
        writer.writeName("customerFirstName");
        writer.writeString(doc.getCustomerFirstName());
        writer.writeName("customerLastName");
        writer.writeString(doc.getCustomerLastName());
        writer.writeEndDocument();
    }

    public Class<AccountDTO> getEncoderClass() {
        return AccountDTO.class;
    }

    public AccountDTO decode(BsonReader reader, DecoderContext decoderContext) {
        reader.readStartDocument();
        String iBAN = reader.readString("IBAN");
        String firstName = reader.readString("customerFirstName");
        String lastName = reader.readString("customerLastName");
        double balance = reader.readDouble("balance");
        String currency = reader.readString("currency");
        long customerId = reader.readInt64("customerId");



        reader.readEndDocument();
        Account account = new Account(iBAN, balance, currency);
        Customer customer = new Customer(firstName, lastName, customerId, account);
        AccountDTO doc = new AccountDTO(account, customer);
        return doc;
    }

}

编解码器提供者:

package utils;

import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecProvider;
import org.bson.codecs.configuration.CodecRegistry;

import dto.AccountDTO;

class MyCodecProvider implements CodecProvider {    
    public <T> Codec<T> get(Class<T> myClass, CodecRegistry codecRegistry) {
        if (myClass== AccountDTO.class) {
            return (Codec<T>) new MyAccountDTOImpCodec(codecRegistry);
        }
        return null;
    }
}

当使用JUnit 运行我的测试时,我得到了这个堆栈:

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

我认为这是一个糟糕的实现,在Node.js 中我会发送我的json 对象,将java 对象发送给MongoDB 似乎很奇怪。

这只是对javadoc 的错误解释还是我的代码中缺少某种形式?

【问题讨论】:

    标签: java mongodb mongodb-java


    【解决方案1】:

    您必须为您的 Java 类实现 编解码器,然后 MongoDB 将能够将 BSON 值解码为 Java 对象并将 Java 对象编码为 BSON 值。看看这个 Mongo Java 驱动文档:http://mongodb.github.io/mongo-java-driver/3.0/bson/codecs/

    这将是代表 MongoDB 集合中文档的 POJO 类:

    class MyDocument {
        private String id;
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        @Override
        public String toString() {
            return "MyDocument [id=" + id + ", name=" + name + "]";
        } 
    }
    

    我们需要创建一个实现Codec 接口 的类,此外还扩展了接口:Encoder&lt;T&gt;Decoder&lt;T&gt;。此类将提供将 MyDocument Java 对象编码和解码为 BSON 文档所需的方法。

    class MyDocumentImpCodec implements Codec<MyDocument> {
    
        private CodecRegistry codecRegistry;
    
        public MyDocumentImpCodec(CodecRegistry codecRegistry) {
            this.codecRegistry = codecRegistry;
        }
    
        public void encode(BsonWriter writer, MyDocument doc, EncoderContext encoderContext) {
            writer.writeStartDocument();
            writer.writeName("_id");
            writer.writeString(doc.getId());
            writer.writeName("name");
            writer.writeString(doc.getName());
            writer.writeEndDocument();
        }
    
        public MyDocument decode(BsonReader reader, DecoderContext decoderContext) {
            reader.readStartDocument();
            String id = reader.readString("_id");
            String name = reader.readString("name");
            reader.readEndDocument();
    
            MyDocument doc = new MyDocument();
            doc.setId(id);
            doc.setName(name);
            return doc;
        }    
    
        public Class<MyDocument> getEncoderClass() {
            return MyDocument.class;
        }
    }
    

    CodecProvider 是 Codec 实例的工厂。

    class MyCodecProvider implements CodecProvider {    
        public <T> Codec<T> get(Class<T> myClass, CodecRegistry codecRegistry) {
            if (myClass == MyDocument.class) {
                return (Codec<T>) new MyDocumentImpCodec(codecRegistry);
            }
            return null;
        }
    }
    

    CodecRegistry 类 包含一组 Codec 实例,这些实例根据它们编码和解码到的 Java 类进行访问。在我们的示例中,CodecRegistry 实例仅获取我们之前定义的 MyCodecProvider 和 default codec registries

    public static MongoCollection<AccountDTO>  getDbCollection() {
        // ...................................................
        CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
            CodecRegistries.fromProviders(new MyCodecProvider()),
            MongoClient.getDefaultCodecRegistry());
    
        MongoClientOptions options = MongoClientOptions
                                        .builder()
                                        .codecRegistry(codecRegistry)
                                        .build();
        // ...................................................
    
        MongoClient mongoClient = new MongoClient(MONGODB_SERVER_IP, options);
    
        MongoDatabase = db = mongoClient.getDatabase(MONGODB_SERVER_DATABASE_NAME);
    
        MongoCollection<MyDocument> collection = db.getCollection(
            MONGODB_SERVER_COLLECTION_NAME, 
            MyDocument.class);
    
        return collection;
    }
    

    实现DAO方法的示例:

    public static void getDocument() {
        FindIterable<MyDocument> iterator = collection.find();
    
        for (MyDocument doc : iterator) {
            System.out.println(doc);
        }
    }
    
    public static void insertDocument() {
        MyDocument doc = new MyDocument();
        doc.setId("1001");
        doc.setName("myName");
    
        collection.insertOne(doc);
    }
    

    【讨论】:

    • 仍然没有时间测试,前几天工作很多。我不会忘记的别担心^^
    • 显示你创建 MongoClient 实例的代码,可能在 Utils.getDbConnect() 中。您是否在我的 getDbCollection 实现中添加了我在 cmets 之间放置的代码?
    • Nvm ,我切换到 Morphia ,不到 1 小时就可以工作了 ^^ 仍然感谢您的帮助。
    猜你喜欢
    • 2015-02-13
    • 1970-01-01
    • 2021-01-07
    • 1970-01-01
    • 2016-06-18
    • 1970-01-01
    • 2019-05-17
    • 2015-09-02
    相关资源
    最近更新 更多