2016-05-17 10 views
8

Wir verwenden MongoDB über Spring Data und verwenden die Operation findAndModify, um vorhandene Entitäten zu aktualisieren oder neue Entitäten zu erstellen.Rückgabe alter und neuer Entitäten aus Spring/MongoDB findAndModify

In der findAndModify können wir konfigurieren, um den alten Zustand der Entität oder der neuen mit returnNew(...) zurückgeben.

Gibt es eine Möglichkeit, alte und neue Entitäten von findAndModify zurückzugeben?

Wir müssen Entitätszustände vor und nach der Aktualisierung vergleichen, deshalb brauchen wir beide Instanzen.

Im Moment sind wir zu requireNew(false) sind greifen und dann manuell eine Kopie der alten Instanz aktualisieren, so etwas wie dieses:

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

Arbeiten aber ist nicht schön, da wir die gleichen Dinge zu wiederholen haben wir tun Sie bereits in der Update auf der Kopie der alten Instanz.

Wir haben auch darüber nachgedacht, zuerst eine alte Instanz zu laden und das Update auszuführen, aber es ist nicht sicher, da die Entität möglicherweise zwischen dem Laden und dem Update geändert wurde. Dies kann mit Versionen und optimistischem Sperren behoben werden, aber das macht die Dinge noch komplizierter.

Antwort

4

Gibt es eine Möglichkeit, alte und neue Entitäten von findAndModify zurückzugeben?

Keine, gibt es keine Möglichkeit, alten und neuen Wert mit findAndModify zurückzukehren.

+0

Ja, sieht aus als gäbe es keinen anderen Weg. – lexicore

0

Nein, es gibt keine Möglichkeit, mit findAndModify alte und neue Werte zurückzugeben.

Aber wenn Sie wollen, bevor Rechtsträger Zustand vergleichen und nach der folgenden Aktualisierung tun Schritte

  1. Kurz bevor die Daten mit Primärschlüssel und Speicher in olddata Variable
  2. in Ihrer findAndModify Abfrage ändern Aktualisierung abrufen returnNew zu wahr es unter newData speichern

Below Probe sudocode werden Sie beide Werte zurück

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

Es kann ein weiteres Update zwischen dem ersten 'find' und dem folgenden' findAndModify' geben, so dass 'oldData' möglicherweise veraltet ist. – lexicore

+0

findAndModify ist Thread-sicher, so dass es nicht passieren wird und da beide Schritte nacheinander auftreten, reicht Ihr Anwendungsfall aus. – rajadilipkolli

+0

Gewindesicherheit hat damit nichts zu tun. Es kann mehrere Threads geben, die Daten parallel verarbeiten. Selbst wenn 'findAndModify' atomar ist, ist eine Folge von' find' und 'findAndModify' nicht. Als nächstes kann auf die Datenbank von verschiedenen Prozessen oder sogar Maschinen zugegriffen werden. Es gibt keine Möglichkeit zu garantieren, dass keine Aktualisierung zwischen 'find' und' findAndUpdate' stattfindet. – lexicore

Verwandte Themen