我们通过Spring Data使用MongoDB,并依赖findAndModify
操作来更新现有实体或创建新实体。
在findAndModify
我们可以配置为使用returnNew(...)
返回实体的旧状态或新状态。
有没有办法从findAndModify
返回旧实体和新实体?
我们需要在更新之前和之后比较实体状态,这就是我们需要两个实例的原因。
目前我们正在使用requireNew(false)
,然后手动更新旧实例的副本,如下所示:
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);
}
工作但并不漂亮,因为我们必须重做旧实例副本上Update
已经执行的相同操作。
我们还考虑过首先加载一个旧实例并运行更新,但它不安全,因为实体可能已在加载和更新之间进行了修改。这可以通过版本和乐观锁定来解决,但这会使事情变得更加复杂。
答案 0 :(得分:4)
有没有办法从findAndModify返回旧实体和新实体?
否,无法使用findAndModify
返回旧值和新值。
答案 1 :(得分:0)
不,使用findAndModify无法返回旧值和新值。
但是如果你想比较更新前后的授权状态,请执行以下步骤
以下示例sudocode将返回两个值
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 = findById(); //query to retrieve existing data
final Data newData = operations.findAndModify(findById, update,
FindAndModifyOptions.options().upsert(true).returnNew(true), Data.class);
return new Pair<Data>(oldData, newData);
}