Angenommen, Sie haben eine Art Datenstruktur, die in einer Art Datenbank beibehalten wird. Nennen wir diese Datenstruktur der Einfachheit halber Person
. Sie müssen nun eine CRUD-API entwerfen, mit der andere Anwendungen Person
s erstellen, lesen, aktualisieren und löschen können . Nehmen wir zur Vereinfachung an, dass auf diese API über eine Art Webdienst zugegriffen wird.
Für die Teile C, R und D von CRUD ist das Design einfach. Ich werde eine C # -ähnliche Funktionsnotation verwenden - die Implementierung könnte SOAP, REST / JSON oder etwas anderes sein:
class Person {
string Name;
DateTime? DateOfBirth;
...
}
Identifier CreatePerson(Person);
Person GetPerson(Identifier);
void DeletePerson(Identifier);
Was ist mit Update? Das Natürlichste wäre
void UpdatePerson(Identifier, Person);
aber wie würden Sie angeben, welche Felder Person
aktualisiert werden sollen?
Lösungen, die ich finden könnte:
Sie können immer verlangen, dass eine vollständige Person übergeben wird, dh der Kunde würde so etwas tun, um das Geburtsdatum zu aktualisieren:
p = GetPerson(id); p.DateOfBirth = ...; UpdatePerson(id, p);
Dies würde jedoch eine Art Transaktionskonsistenz oder eine Sperrung zwischen Get und Update erfordern. Andernfalls können Sie eine andere Änderung überschreiben, die parallel von einem anderen Client vorgenommen wurde. Dies würde die API viel komplizierter machen. Darüber hinaus ist es fehleranfällig, da der folgende Pseudocode (unter der Annahme einer Client-Sprache mit JSON-Unterstützung)
UpdatePerson(id, { "DateOfBirth": "2015-01-01" });
- was richtig aussieht - würde nicht nur DateOfBirth ändern, sondern auch alle anderen Felder auf null zurücksetzen.
Sie können alle Felder ignorieren
null
. Wie würden Sie dann einen Unterschied machen, ob Sie es nicht ändernDateOfBirth
oder absichtlich auf null ändern ?Ändern Sie die Signatur in
void UpdatePerson(Identifier, Person, ListOfFieldNamesToUpdate)
.Ändern Sie die Signatur in
void UpdatePerson(Identifier, ListOfFieldValuePairs)
.Verwenden Sie eine Funktion des Übertragungsprotokolls: Sie können beispielsweise alle Felder ignorieren, die nicht in der JSON-Darstellung der Person enthalten sind. Dies erfordert jedoch normalerweise, dass Sie den JSON selbst analysieren und die integrierten Funktionen Ihrer Bibliothek (z. B. WCF) nicht verwenden können.
Keine der Lösungen erscheint mir wirklich elegant. Dies ist sicherlich ein häufiges Problem. Was ist also die Best-Practice-Lösung, die von allen verwendet wird?
Person
Lassen Sie für neu erstellte Instanzen, die noch nicht persistiert sind, und für den Fall, dass der Bezeichner als Teil des Persistenzmechanismus festgelegt wird, ihn einfach auf null. Für die Antwort verwendet JPA eine Versionsnummer. Wenn Sie Version 23 lesen und das Element aktualisieren, wenn die Version in DB 24 ist, schlägt der Schreibvorgang fehl.