从Spring / MongoDB findAndModify返回旧实体和新实体

时间:2016-05-17 12:15:26

标签: spring mongodb mongodb-query spring-data mongodb-java

我们通过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已经执行的相同操作。

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

2 个答案:

答案 0 :(得分:4)

  

有没有办法从findAndModify返回旧实体和新实体?

,无法使用findAndModify返回旧值和新值。

答案 1 :(得分:0)

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

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

  1. 在更新之前,使用主键检索数据并存储在oldData变量
  2. 中 在您的findAndModify查询中
  3. 将returnNew更改为true以将其保存在newData下
  4. 以下示例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);
        }