简体   繁体   中英

Inserting Java Object to MongoDB Collection Using Java

I am trying to insert a whole Java object into a MongoDB Collection using Java. I am getting following error:

Error :

Exception in thread "main" java.lang.IllegalArgumentException: can't serialize class net.yogesh.test.Employee
    at org.bson.BSONEncoder._putObjectField(BSONEncoder.java:185)
    at org.bson.BSONEncoder.putObject(BSONEncoder.java:119)
    at org.bson.BSONEncoder.putObject(BSONEncoder.java:65)
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:176)
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:134)
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:129)
    at com.mongodb.DBCollection.save(DBCollection.java:418)
    at net.yogesh.test.test.main(test.java:31)

Emplyoee.java (POJO)

package net.yogesh.test;

import java.io.Serializable;

public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;
    private long no;
    private String name;

    public Employee() {
    }

    public long getNo() {
        return no;
    }

    public void setNo(long no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Main Method Class (test.java)

package net.yogesh.test;

import java.net.UnknownHostException;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

public class test {

    public static void main(String[] args) throws UnknownHostException,
            MongoException {

        Mongo mongo = new Mongo("localhost", 27017);
        DB db = mongo.getDB("test");

        Employee employee = new Employee();
        employee.setNo(1L);
        employee.setName("yogesh");


        BasicDBObject basicDBObject = new BasicDBObject("Name", employee);

        DBCollection dbCollection = db.getCollection("NameColl");

        dbCollection.save(basicDBObject);   

    }

}

Can anybody explain why I am getting this error?

I'm a little confused as to know why you'd think this would work in the first place. The first thing you need to know is how to map your POJO to a MongoDB document. Currently, you're not telling the system(your code) how to do that.

You can either use a mapping library for this (Morphia comes to mind) or use ReflectionDBObject. Either solution allows you to map POJO to MongoDB document or MongoDB document to POJO(the former way is a lot more nicely than the latter).

DB db = mongoClient.getDB( "mydb" );

coll = db.getCollection("testCollection");

Employee emp = new Employee();
emp.setId("1001");
emp.setName("John Doe");

//Converting a custom Class(Employee) to BasicDBObject
Gson gson = new Gson();
BasicDBObject obj = (BasicDBObject)JSON.parse(gson.toJson(emp));
coll.insert(obj);
findEmployee(new BasicDBObject("id","1001"));


public static void findEmployee(BasicDBObject query){

    DBCursor cursor = coll.find(query);

    try {
       while(cursor.hasNext()) {
          DBObject dbobj = cursor.next();
        //Converting BasicDBObject to a custom Class(Employee)
          Employee emp = (new Gson()).fromJson(dbobj.toString(), Employee.class);
          System.out.println(emp.getName());
       }
    } finally {
       cursor.close();
    }

}

I thought that it would be useful to post code that did conversions both ways.
Storing an Employee Object
Finding and re-creating an employee Object
Hope this is useful..

Pro
you continue to work with strong typed objects as you wanted to

Contra
Some people really dislike : extends


package foo;
import com.mongodb.BasicDBObject;

public class Employee extends BasicDBObject {

private static final long serialVersionUID = 2105061907470199595L;
//should be something shorter as "name" like "n" 
//here just use name to conform your  sample
public static final String NAME = "name";
public static final String NO = "no";
public static final String COLLECTION_NAME = "employee";

public Long getNo() {
    return getLong(NO);
}

public void setNo(long no) {
    put(NO, no);
}

public String getName() {
    return getString(NAME);
}

public void setName(String name) {
    put(NAME, name);
}

}


package foo;
import java.net.UnknownHostException;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

public class Test {

public static void main(String[] args) throws UnknownHostException,
        MongoException {

    Mongo mongo = new Mongo("localhost", 27017);
    DB db = mongo.getDB("yeahMongo");

    Employee employee = new Employee();
    employee.setNo(1L);
    employee.setName("yogesh");

    DBCollection employeeCollection = null ;
    employeeCollection = db.getCollection(Employee.COLLECTION_NAME);

    employeeCollection.save(employee);

    System.err.println(employeeCollection.findOne());

}

}

In addition to morphia you should take a look to jongo : http://jongo.org/ jongo use the same form syntax as js mongo engine, and I found it great point for a beginner. You don't have to switch your mental map between mongojs and java. you can use the js sample with little changes.

You can convert your java object into json string using the gson library and then insert it in mongodb.

Eg:

Gson gson = new Gson();
String json = gson.toJson(Employee);    
BasicDBObject basicDBObject = new BasicDBObject("Name", json );          
DBCollection dbCollection = db.getCollection("NameColl");          
dbCollection.save(basicDBObject);    

There have been several changes since this question was asked. Using test.java in the question, here is what worked for me using Google's Gson :

import com.google.gson.Gson;
import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

public class test {
  public static void main(String[] args) {
    MongoClient mongoClient = new MongoClient(); // Connect with default settings i.e. localhost:27017
    MongoDatabase db = mongoClient.getDatabase("test"); // Get database "test". Creates one if it doesn't exist
    Employee employee = new Employee(); // Create java object
    employee.setNo(1L);
    employee.setName("yogesh");
    // Deserialize object to json string
    Gson gson = new Gson();
    String json = gson.toJson(employee);
    // Parse to bson document and insert
    Document doc = Document.parse(json);
    db.getCollection("NameColl").insertOne(doc);

    // Retrieve to ensure object was inserted
    FindIterable<Document> iterable = db.getCollection("NameColl").find();
    iterable.forEach(new Block<Document>() {
      @Override
      public void apply(final Document document) {
        System.out.println(document); // See below to convert document back to Employee
      }
    });

  }
}

You can also use Gson to convert retrieved bson document back to Java object:

Gson gson = new Gson();
Employee emp = gson.fromJson(document.toJson(), Employee.class);

With MongoDB you cannot insert your Java bean in the DB, but you have to remap them to MongoDB Object.

In your case you have to do:

BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.put("no", employee.getNo());
basicDBObject.put("name", employee.getName());

Hopefully this will work for you and you can get help from it. I performed database operations(insert,delete, update, get, getall) and used Person object for operations in MongoDB with java for demo purpose.

  1. Database connection class

Connection.java

package test;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.client.MongoDatabase;

public class Connection {
    public MongoClient mongo;
    private String db;
    public MongoDatabase database;
    private static Connection instance;

    private Connection() {
        db = "chatsystem";
        CodecRegistry pojoCodecRegistry = fromRegistries(MongoClient.getDefaultCodecRegistry(),
                fromProviders(PojoCodecProvider.builder().automatic(true).build()));
        mongo = new MongoClient("localhost", MongoClientOptions.builder().codecRegistry(pojoCodecRegistry).build());
        database = mongo.getDatabase(db);

    }

    public static Connection getInstance() {
        if (instance == null) {
            instance = new Connection();
            return instance;
        } else {
            return instance;
        }
    }

}
  1. Model Class

Person.java

package test;

import org.bson.types.ObjectId;

public class Person {

    public Person() {
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFname() {
        return fname;
    }

    public void setFname(String fname) {
        this.fname = fname;
    }

    public String getLname() {
        return lname;
    }

    public void setLname(String lname) {
        this.lname = lname;
    }

    private ObjectId id;

    public Person(String username, String email, String password, String fname, String lname) {
        super();
        this.username = username;
        this.email = email;
        this.password = password;
        this.fname = fname;
        this.lname = lname;
    }

    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    private String username;
    private String email;
    private String password;
    private String fname;
    private String lname;
}
  1. Main class

test.java

package test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static com.mongodb.client.model.Filters.*;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;

public class test {
    private MongoCollection<Person> person;
    Connection conn;
    public void getCollection() {
        conn = Connection.getInstance();
        person = conn.database.getCollection("person", Person.class);
    }
    public static void main(String[] args) throws Exception {
        test t = new test();
        t.getCollection();
        Person p = new Person();
        p.setEmail("test@test.com");
        p.setFname("ftest");
        p.setLname("ltest");
        p.setPassword("testtest");
        p.setUsername("test123");


        // insert person type objects in database
        t.insertPerson(p);


        // get all persons from database
        List<Person> pp = t.getAllPersons();
        Person pt = pp.get(0);
        System.out.println(pt.getEmail());
        System.out.println(pt.getId());


        // get one person from database by username filter

                 // pass username of person in method argument
        Person ph = t.getOnePerson("test123");
        System.out.println(ph.getEmail());
        System.out.println(ph.getId());


        // update/edit person by username filter
                // pass username of person in method argument
        t.updatePerson("test123");


        // delete person by username filter
               // pass username of person in method argument
        t.removePerson("updatetest123");

    }

    public void insertPerson(Person p) {

        person.insertOne(p);
    }

    public List<Person> getAllPersons() {
        FindIterable<Person> iterable = person.find();
        Iterator it = iterable.iterator();
        List<Person> allPersons = new ArrayList<>();
        while (it.hasNext()) {
            Person per = (Person) it.next();
            allPersons.add(per);
        }
        return allPersons;
    }

    public Person getOnePerson(String username) {
        return person.find(eq("username", username)).first();
    }

    public void updatePerson(String username) {
        Person p = new Person();
        p.setEmail("update@test.com");
        p.setFname("updateftest");
        p.setLname("updateltest");
        p.setPassword("updatetesttest");
        p.setUsername("updatetest123");
        person.replaceOne(eq("username", username), p);

    }

    public void removePerson(String username) {
        person.deleteOne(eq("username", username));
    }



}

Highly recommend MongoJack , a decent library to map Java objects to/from MongoDB documents.

The code would be something like below:

import java.util.Arrays;
import org.mongojack.JacksonDBCollection;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;

public class Test {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("localhost", 27017)));
        DB db = mongoClient.getDB("test");

        Employee employee = new Employee();
        employee.setNo(1L);
        employee.setName("yogesh");

        JacksonDBCollection<Employee, String> collectionData = JacksonDBCollection.wrap(db.getCollection("NameColl"), Employee.class, String.class);
        collectionData.save(employee);
        mongoClient.close();
    }

}

(PS: Currently I'm using mongo-java-driver v3.2.2, and mongojack v2.6.1)

Use BasicDBObjectBuilder to convert your POJO to an instance of DBObject which a DBCollection can save:

import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;

public class Employee {
    private long no;
    private String name;

    // Getters and Setters

    public DBObject toDBObject() {
        BasicDBObjectBuilder builder = BasicDBObjectBuilder
                .start("no", no)
                .append("name", name);
        return builder.get();
    }
}

In order to save, just call toDBObject() on POJO instance and provide it to collection:

public class test {

    public static void main(String[] args) throws UnknownHostException,
            MongoException {
        ...
        DBCollection dbCollection = db.getCollection("NameColl");

        Employee employee = new Employee();
        employee.setNo(1L);
        employee.setName("yogesh");

        dbCollection.save(employee.toDBObject());
    }
}

Using this approach:

  • You don't need to manually create a DBObject every time
  • You don't need to mess up your POJO by extending Mongo classes (what if your POJO is already extending a class?)
  • You don't need a Json mapper [and its annotations on POJO fields]
  • You only have dependency to java-mongo-driver jar

I have the same error, when I try to insert a java BasicDBObject into a MongoDb Collection.

My object is created from a Xml converted to Json.

java.lang.IllegalArgumentException: can't serialize class net.sf.json.JSONNull
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:299)
    at org.bson.BasicBSONEncoder.putMap(BasicBSONEncoder.java:339)
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:261)

This error is caused by empty tags in Xml; when I removed all empty tags, then I solved it.

Just use "insertOne" method, not save.

    MongoCollection collection;
    String collectionName = "somename";
    String jsonObject = "{}";

    if (!mongoTemplate.collectionExists(collectionName)) {
        collection = mongoTemplate.createCollection(collectionName);
        logger.info("Collection %s was successfully created", collectionName);
    } else {
        collection = mongoTemplate.getCollection(collectionName);
    }

    collection.insertOne(Document.parse(jsonObject));

Since nobody has mentioned it - I think there might be a solution to this using bson4jackson . This bills itself as a fast encoder.

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