Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoTemplate upsert - easy way to make Update from pojo (which user has editted)?

Tags:

Here is a simple pojo:

public class Description {
    private String code;
    private String name;
    private String norwegian;
    private String english;
}

And please see the following code to apply an upsert to MongoDb via spring MongoTemplate:

Query query = new Query(Criteria.where("code").is(description.getCode()));
Update update = new Update().set("name", description.getName()).set("norwegian", description.getNorwegian()).set("english", description.getEnglish());
mongoTemplate.upsert(query, update, "descriptions");

The line to generate the Update object specifies every field of the Item class manually.

But if my Item object changes then my Dao layer breaks.

So is there a way to avoid doing this, so that all fields from my Item class are applied automatically to the update?

E.g.

Update update = new Update().fromObject(item);

Note that my pojo does not extend DBObject.

like image 219
vikingsteve Avatar asked Nov 15 '13 12:11

vikingsteve


People also ask

How do I update MongoTemplate?

And please see the following code to apply an upsert to MongoDb via spring MongoTemplate: Query query = new Query(Criteria. where("code").is(description. getCode())); Update update = new Update().

Which is better MongoTemplate or MongoRepository?

So I'd say that MongoTemplate is a better option, unless you have a very elaborated POJO model or need the custom queries capabilities of MongoRepository for some reason. Good points/examples. However your race condition example and undesired result can be avoided using @Version to prevent that very scenario.

What is the difference between MongoOperations and MongoTemplate?

MongoTemplate provides a simple way for you to save, update, and delete your domain objects and map those objects to documents stored in MongoDB. You can save, update and delete the object as shown below. MongoOperations is the interface that MongoTemplate implements.


2 Answers

I found a pretty good solution for this question

//make a new description here
Description d = new Description();
d.setCode("no");
d.setName("norwegian");
d.setNorwegian("norwegian");
d.setEnglish("english");

//build query
Query query = new Query(Criteria.where("code").is(description.getCode()));

//build update
DBObject dbDoc = new BasicDBObject();
mongoTemplate.getConverter().write(d, dbDoc); //it is the one spring use for convertions.
Update update = Update.fromDBObject(dbDoc);

//run it!
mongoTemplate.upsert(query, update, "descriptions");

Plz note that Update.fromDBObject return an update object with all fields in dbDoc. If you just want to update non-null fields, you should code a new method to exclude null fields.

For example, the front-end post a doc like below:

//make a new description here
Description d = new Description();
d.setCode("no");
d.setEnglish("norwegian");

We only need to update the field 'language':

//return Update object
public static Update fromDBObjectExcludeNullFields(DBObject object) {
    Update update = new Update();       
    for (String key : object.keySet()) {
        Object value = object.get(key);
        if(value!=null){
            update.set(key, value);
        }
    }
    return update;
}

//build udpate
Update update = fromDBObjectExcludeNullFields(dbDoc);
like image 194
PaniniGelato Avatar answered Sep 25 '22 06:09

PaniniGelato


The solution for a new spring-data-mongodb version 2.X.X.

The API has evolved, since 2.X.X version there is:

Update.fromDocument(org.bson.Document object, String... exclude)

instead of (1.X.X):

Update.fromDBObject(com.mongodb.DBObject object, String... exclude)

The full solution:

//make a new description here
Description d = new Description();
d.setCode("no");
d.setName("norwegian");
d.setNorwegian("norwegian");
d.setEnglish("english");
Query query = new Query(Criteria.where("code").is(description.getCode()));

Document doc = new Document(); // org.bson.Document
mongoTemplate.getConverter().write(item, doc);
Update update = Update.fromDocument(doc);

mongoTemplate.upsert(query, update, "descriptions");

It works!

like image 24
Dawid Naczke Avatar answered Sep 23 '22 06:09

Dawid Naczke