简体   繁体   中英

How to insert object in MongoDB 3.2 document?

I have a User

public class User {
    private String name;
    private String email;

    public User () {  }

    public User(String name) {
        this.name = name;
    }

    public User(String name, String email) {
        this(name);
        this.email = email;
    }
    // getters and setters
}

Also I have simple POJO Comment

public class Comment {
    private String comment;
    private Date date;
    private String author;

    public Comment() { }

    public Comment(String comment, Date date, String author) {
        this.comment = comment;
        this.date = date;
        this.author = author;
    }
    // getters and setters
}

How I want insert new user into collection with some kind of comments about him like this:

public static void main(String[] args) {
    MongoClient client = new MongoClient();
    MongoDatabase db = client.getDatabase("example");
    MongoCollection<Document> collection = db.getCollection("object_arrays");

    collection.drop();

    List<Comment> reviews = new ArrayList<Comment>(){{
        add(new Comment("cool guy", new Date(), "John Doe"));
        add(new Comment("best joker", new Date(), "Vas Negas"));
        add(new Comment("very stupid but very funny man", new Date(), "Bill Murphy"));
    }};
    Document user = new Document();
    user.append("user", new User("0xFF", "email@email.com"))
            .append("reviews", reviews)
            .append("createDate", new Date());
    collection.insertOne(user);
}

Unfortunately, I've got Exception:

    Exception in thread "main" org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class com.mongodb.course.com.mongodb.course.model.User.
    at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
    at org.bson.codecs.configuration.ChildCodecRegistry.get(ChildCodecRegistry.java:51)
    at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:174)
    at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:189)
    at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:131)
    at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
    at com.mongodb.connection.InsertCommandMessage.writeTheWrites(InsertCommandMessage.java:101)
    at com.mongodb.connection.InsertCommandMessage.writeTheWrites(InsertCommandMessage.java:43)
    at com.mongodb.connection.BaseWriteCommandMessage.encodeMessageBodyWithMetadata(BaseWriteCommandMessage.java:129)
    at com.mongodb.connection.RequestMessage.encodeWithMetadata(RequestMessage.java:160)
    at com.mongodb.connection.WriteCommandProtocol.sendMessage(WriteCommandProtocol.java:212)
    at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:101)
    at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:67)
    at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:37)
    at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:159)
    at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:286)
    at com.mongodb.connection.DefaultServerConnection.insertCommand(DefaultServerConnection.java:115)
    at com.mongodb.operation.MixedBulkWriteOperation$Run$2.executeWriteCommandProtocol(MixedBulkWriteOperation.java:455)
    at com.mongodb.operation.MixedBulkWriteOperation$Run$RunExecutor.execute(MixedBulkWriteOperation.java:646)
    at com.mongodb.operation.MixedBulkWriteOperation$Run.execute(MixedBulkWriteOperation.java:401)
    at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:179)
    at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:168)
    at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:230)
    at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:221)
    at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:168)
    at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:74)
    at com.mongodb.Mongo.execute(Mongo.java:781)
    at com.mongodb.Mongo$2.execute(Mongo.java:764)
    at com.mongodb.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:515)
    at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:306)
    at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:297)
    at com.mongodb.course.week3.ArrayListWithObject.main(ArrayListWithObject.java:34)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

I understand that Java driver for MongoDB can't convert my object into Document and it want some kind of converter. Also I know about Codec , CodecRegistry and CodecProvider interfaces. By the way, is there a simpler way to convert object into mongo document? Can you show me example how can I do it? Thank you.

The problem with the code you posted is that it doesnt know by default how to serialise your pojo objects into Json to save them into the databse. You can do this with the MongoDB Java drivers, but you need to do some work to serialise the Comment ArrayList and User pojos. If you add some Jackson mapping code you can do this as follows:

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.bson.Document;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

public class Problem {
    public static void main(String[] args) {
        try (final MongoClient client = new MongoClient()) {
            final MongoDatabase db = client.getDatabase("example");
            final MongoCollection<Document> collection = db.getCollection("object_arrays");

            collection.drop();

            final List<Comment> reviews = new ArrayList<Comment>() {
                {
                    add(new Comment("cool guy", new Date(), "John Doe"));
                    add(new Comment("best joker", new Date(), "Vas Negas"));
                    add(new Comment("very stupid but very funny man", new Date(), "Bill Murphy"));
                }
            };

            final ObjectMapper mapper = new ObjectMapper();
            final User user = new User("0xFF", "email@email.com");
            try {
                //Create a Document representation of the User object
                final String userJson = mapper.writeValueAsString(user);
                final Document userDoc = Document.parse(userJson);

                //Convert the review ArrayList into a Mongo Document.  Need to amend this if not using Java8
                final List<Document> reviewDocs = reviews.stream().map(convertToJson())
                        .map(reviewJson -> Document.parse(reviewJson)).collect(Collectors.toList());

                //Wrap it all up to it can be saved to the database
                final Document wrapperDoc = new Document();
                wrapperDoc.append("user", userDoc).append("reviews", reviewDocs).append("createDate", new Date());
                collection.insertOne(wrapperDoc);
            } catch (final JsonProcessingException e) {
                e.printStackTrace();
            }
        }
    }

    private static Function<Comment, String> convertToJson() {
        final ObjectMapper mapper = new ObjectMapper();
        return review -> {
            try {
                return mapper.writeValueAsString(review);
            } catch (final JsonProcessingException e) {
                e.printStackTrace();
            }
            return "";
        };
    }
}

*this uses some Java8 code which you might need to change depending on which version of Java you're using

As the other answer on this question says there are frameworks out there that can combine the serialisation of Objects and interaction with MongoDB so that you dont need to hand-crank the serialisation code. For example Spring has a Mongo driver, and I have used another called Jongo, which I have found to be quite good.

If you want to work with Java objects like this, Morphia is your best bet. There is work being done now to support arbitrary Java classes like you're trying but it's not done yet.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM