Załóżmy, że masz jakąś strukturę danych, która jest utrwalona w jakiejś bazie danych. Dla uproszczenia nazwijmy tę strukturę danych Person. Masz teraz zadanie zaprojektowania interfejsu CRUD API, który pozwala innym aplikacjom tworzyć, czytać, aktualizować i usuwać Persons. Dla uproszczenia załóżmy, że dostęp do tego interfejsu API można uzyskać za pośrednictwem usługi internetowej.
W przypadku części CRUD C, R i D konstrukcja jest prosta. Użyję notacji funkcjonalnej podobnej do C # - implementacją może być SOAP, REST / JSON lub coś innego:
class Person {
string Name;
DateTime? DateOfBirth;
...
}
Identifier CreatePerson(Person);
Person GetPerson(Identifier);
void DeletePerson(Identifier);
Co z aktualizacją? Naturalną rzeczą do zrobienia byłoby
void UpdatePerson(Identifier, Person);
ale jak określisz, które pola Personchcesz zaktualizować?
Rozwiązania, które mógłbym wymyślić:
Zawsze możesz wymagać przekazania pełnej Osoby, tzn. Klient zrobiłby coś takiego, aby zaktualizować datę urodzenia:
p = GetPerson(id); p.DateOfBirth = ...; UpdatePerson(id, p);Wymagałoby to jednak pewnego rodzaju spójności transakcyjnej lub blokowania między Get a Update; w przeciwnym razie możesz zastąpić inną zmianę wykonaną równolegle przez innego klienta. Sprawiłoby to, że interfejs API byłby znacznie bardziej skomplikowany. Ponadto jest podatny na błędy, ponieważ następujący pseudo-kod (zakładając język klienta z obsługą JSON)
UpdatePerson(id, { "DateOfBirth": "2015-01-01" });- który wygląda poprawnie - nie tylko zmieni DateOfBirth, ale także zresetuje wszystkie inne pola do null.
Możesz zignorować wszystkie pola, które są
null. Jak jednak zrobiłbyś różnicę między niezmienianiemDateOfBirtha celowym zmienianiem go na zero ?Zmień podpis na
void UpdatePerson(Identifier, Person, ListOfFieldNamesToUpdate).Zmień podpis na
void UpdatePerson(Identifier, ListOfFieldValuePairs).Użyj pewnej funkcji protokołu transmisji: na przykład możesz zignorować wszystkie pola nie zawarte w reprezentacji JSON osoby. Zwykle wymaga to jednak samodzielnego przeanalizowania JSON i niemożności korzystania z wbudowanych funkcji biblioteki (np. WCF).
Żadne z rozwiązań nie wydaje mi się naprawdę eleganckie. Z pewnością jest to powszechny problem, więc jakie jest najlepsze rozwiązanie stosowane przez wszystkich?
Personinstancji, które nadal nie są utrwalane, a jeśli identyfikator jest ustalany jako część mechanizmu trwałości, pozostaw go zerowy. Jeśli chodzi o odpowiedź, JPA używa numeru wersji; jeśli czytasz wersję 23, po zaktualizowaniu elementu, jeśli wersja w DB to 24, zapis nie powiedzie się.