从 Spring/MongoDB findAndModify 返回新旧实体

Returning both old and new entities from Spring/MongoDB findAndModify

我们通过 Spring 数据使用 MongoDB 并依靠 findAndModify 操作来更新现有实体或创建新实体。

findAndModify 中,我们可以配置为 return 实体的旧状态或使用 returnNew(...) 的新状态。

有什么方法可以 return 来自 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 中已经做过的事情。

我们还考虑过先加载一个旧实例,然后 运行 更新,但这并不安全,因为实体可能在加载和更新之间被修改。这可以通过版本和乐观锁定来解决,但这会使事情变得更加复杂。

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

,没有办法 return 旧值和新值 findAndModify

不,无法使用 findAndModify return 旧值和新值。

但是如果你想比较更新前后的实体状态,请执行以下步骤

  1. 在更新之前使用主键检索数据并存储在 oldData 变量中
  2. 在您的 findAndModify 查询中将 returnNew 更改为 true 以将其保存在 newData

下面的示例 sudocode 将 return 你的两个值

    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);
    }