Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning both old and new entities from Spring/MongoDB findAndModify

We're using MongoDB via Spring Data and rely on the findAndModify operation to update existing entities or create new ones.

In the findAndModify we can configure to return old state of the entity or the new one using returnNew(...).

Is there some way to return both old and new entities from findAndModify?

We need to compare entity states before and after update, this is why we need both instances.

At the moment we're resorting to requireNew(false) and then manually update a copy of the old instance, something like this:

public Pair<Data> saveItems(String id, List<Item> items) {
    final Query findById = ...;

    final Update update = new Update();
    // This is what we actually update
    update.set(ENTITY_FIELD_ITEMS, newItems);
    update.inc(ENTITY_FIELD_VERSION, 1);
    // Try updating and return the old data 
    final Data oldData = operations.findAndModify(findById, update,
        FindAndModifyOptions.options().upsert(true).returnNew(false), Data.class);

    // Copy or create new instance
    final Data newData;
    if (oldData == null) {
        newData = new Data(id);
    }
    else {
        newData = new Data(oldData);
    }
    // Apply the same update
    newData.setItems(newItems);
    newData.incVersion();
    return new Pair<Data>(oldData, newData);
}

Works but isn't pretty as we have to redo the same things we already do in the Update on the copy of the old instance.

What we've also considered was first loading an old instance and the running the update but it's not safe as the entity may have been modified between the load and the update. This may be addressed with versions and optimistic locking, but that makes things even more complicated.

like image 580
lexicore Avatar asked May 17 '16 12:05

lexicore


People also ask

Which option should be used with the findAndModify () command to return the modified document instead of the original document?

MongoDB – FindAndModify() Method. The findAndModify() method modifies and return a single document that matches the given criteria. By default, this method returns a pre-modification document. To return the document with the modifications made on the update, use the new option and set its value to true.

Which is better MongoTemplate or MongoRepository?

MongoTemplate is a bit more lower level where you need to write your own queries. With embedded documents and denormalization it can be easier to write complex queries with MongoTemplate. For simple things I would use MongoRepository. I've seen some examples where both are used together in a hybrid approach.

What is @document annotation in spring boot?

@Document is an annotation provided by Spring data project. It is used to identify a domain object, which is persisted to MongoDB. So you can use it to map a Java class into a collection inside MongoDB. If you don't use Spring Data, you don't need this annotation.

Is findAndModify Atomic?

Concurrency ControlA findAndModify operation on a document is atomic: if the find condition matches a document, the update is performed on that document. Concurrent queries and additional updates on that document are not affected until the current update is complete.


1 Answers

Is there some way to return both old and new entities from findAndModify?

No, there's no way to return both old and new value with findAndModify.

like image 104
styvane Avatar answered Nov 15 '22 04:11

styvane