具有特定文档类的MongoDB getCollection

时间:2016-04-09 19:44:55

标签: java mongodb mongodb-java

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

getCollection javadoc说:

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

}

CodecProvider:

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的错误解释还是我的代码缺乏?

1 个答案:

答案 0 :(得分:3)

您必须为Java类实现 Codec ,然后MongoDB将能够将BSON值解码为Java对象并将Java对象编码为BSON值。看看这个Mongo Java Driver Doc: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<T>Decoder<T>。该类将提供将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);
}