2016-05-17 4 views
8

Springデータを使用してMongoDBを使用しています。findAndModify操作を使用して既存のエンティティを更新するか、新しいエンティティを作成します。Spring/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に既にあります。

古いインスタンスをロードしてアップデートを実行していたものの、ロードとアップデートの間でエンティティが変更されている可能性があるため安全ではありません。これは、バージョンと楽観的なロックで対処できるかもしれませんが、それは事態をさらに複雑にします。

答えて

4

findAndModifyから古いエンティティと新しいエンティティの両方を返す方法はありますか?

findAndModifyで新旧両方の値を返す方法はありません。

+0

もう、別の方法はないようですね。 – lexicore

0

いいえ、findAndModifyで古い値と新しい値の両方を返す方法はありません。

しかし、あなたは前に、以下

  1. ステップ行う更新した後entitiyの状態を比較したい場合はちょうどあなたのfindAndModifyクエリの変更returnNewにして、変数OLDDATAの主キーと店舗
  2. を使用してデータを取得更新する前に真のサンプルsudocode下にあるnewData

で保存することがあなたの両方の値を返します

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

最初の 'find'と' findAndModify'の間に別の更新があるかもしれないので、 'oldData'は時代遅れかもしれません。 – lexicore

+0

findAndModifyはスレッドセーフなので、発生しません。両方のステップが次々と発生するため、ユースケースで十分です。 – rajadilipkolli

+0

スレッドの安全性はこれとは関係ありません。並列にデータを処理する複数のスレッドが存在する可能性があります。したがって、 'findAndModify'がアトミックであっても、' find'と 'findAndModify'のシーケンスはアトミックではありません。次に、異なるプロセスまたは機械からデータベースにアクセスすることができます。 'find'と' findAndUpdate'の間で更新操作が起こらないことを保証する方法はありません。 – lexicore

関連する問題