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.
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
.