2016-05-17 9 views
8

Usiamo MongoDB tramite Spring Data e facciamo affidamento sull'operazione findAndModify per aggiornare entità esistenti o crearne di nuove.Restituzione di vecchie e nuove entità da Spring/MongoDB findAndModify

Nel findAndModify possiamo configurare per restituire lo stato precedente dell'entità o quello nuovo utilizzando returnNew(...).

C'è un modo per restituire sia le vecchie che le nuove entità da findAndModify?

Abbiamo bisogno di confrontare gli stati di entità prima e dopo l'aggiornamento, questo è il motivo per cui abbiamo bisogno di entrambe le istanze.

Al momento stiamo ricorrere a requireNew(false) e quindi aggiornare manualmente una copia del vecchio esempio, qualcosa di simile:

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

lavori ma non è bella come dobbiamo rifare le stesse cose che fare già nello Update sulla copia della vecchia istanza.

Quello che abbiamo anche considerato è stato il primo caricamento di una vecchia istanza e l'esecuzione dell'aggiornamento ma non è sicuro in quanto l'entità potrebbe essere stata modificata tra il carico e l'aggiornamento. Questo può essere risolto con versioni e blocco ottimistico, ma questo rende le cose ancora più complicate.

risposta

4

C'è un modo per restituire sia vecchie che nuove entità da findAndModify?

No, non c'è modo di tornare vecchi e nuovo valore con findAndModify.

+0

Sì, sembra che non ci sia altro modo. – lexicore

0

No, non è possibile restituire sia il valore vecchio che il nuovo con findAndModify.

Ma se si desidera confrontare lo stato entitiy prima e dopo l'aggiornamento fare il seguito passaggi

  1. Appena prima di aggiornare recuperare i dati utilizzando la chiave primaria e conservare in OldData variabile
  2. nella findAndModify cambiamento interrogazione returnNew a fedele a salvarlo con newData

seguito sudocode campione si ritorna entrambi i valori

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

Potrebbe esserci un altro aggiornamento tra il primo 'find' e il seguente' findAndModify', quindi 'oldData' potrebbe essere obsoleto. – lexicore

+0

findAndModify è thread-safe, quindi non accadrà e poiché entrambi i passaggi si verificano uno dopo l'altro il tuo caso d'uso sarà sufficiente. – rajadilipkolli

+0

La sicurezza del filo non ha nulla a che fare con questo. Potrebbero esserci diversi thread che elaborano i dati in parallelo. Quindi, anche se 'findAndModify' è atomico, una sequenza di' find' e 'findAndModify' non lo è. Successivamente, è possibile accedere al database da processi diversi o persino da macchine. Non c'è modo di garantire che non avvenga alcuna operazione di aggiornamento tra 'find' e' findAndUpdate'. – lexicore

Problemi correlati