Скажімо, у вас є якась структура даних, яка зберігається в якійсь базі даних. Для простоти назвемо цю структуру даних Person
. Тепер вам покладено завдання створити API CRUD, який дозволяє іншим програмам створювати, читати, оновлювати та видаляти Person
s. Для простоти припустимо, що до цього API можна отримати доступ через якусь веб-службу.
Для частин CRUD C, R і D конструкція проста. Я буду використовувати функцію C # -подобних позначень - реалізація може бути SOAP, REST / JSON або щось інше:
class Person {
string Name;
DateTime? DateOfBirth;
...
}
Identifier CreatePerson(Person);
Person GetPerson(Identifier);
void DeletePerson(Identifier);
Що з оновленням? Природно, що було б зробити
void UpdatePerson(Identifier, Person);
але як би ви вказали, які поля Person
оновити?
Рішення, які я міг би придумати:
Ви завжди можете вимагати передачі повної особи, тобто клієнт зробить щось подібне, щоб оновити дату народження:
p = GetPerson(id); p.DateOfBirth = ...; UpdatePerson(id, p);
Однак це вимагає певної послідовності транзакцій або блокування між Get і Update; в іншому випадку ви можете перезаписати деякі інші зміни, зроблені паралельно іншим клієнтом. Це зробило б API набагато складнішим. Крім того, він схильний до помилок, оскільки наступний псевдо-код (припускаючи мову клієнта з підтримкою JSON)
UpdatePerson(id, { "DateOfBirth": "2015-01-01" });
- що виглядає правильно - не лише змінить DateOfBirth, але й скине всі інші поля на нуль.
Ви можете ігнорувати всі поля, які є
null
. Однак як би ви змінили зміну,DateOfBirth
а не навмисно змінювали її на нульову ?Змініть підпис на
void UpdatePerson(Identifier, Person, ListOfFieldNamesToUpdate)
.Змініть підпис на
void UpdatePerson(Identifier, ListOfFieldValuePairs)
.Використовуйте деяку функцію протоколу передачі: Наприклад, ви можете ігнорувати всі поля, які не містяться в представленні JSON Особи. Однак для цього зазвичай потрібно самостійно проаналізувати JSON і не мати можливості використовувати вбудовані функції вашої бібліотеки (наприклад, WCF).
Жодне з рішень мені не здається справді елегантним. Безумовно, це поширена проблема, тож яке найкраще практичне рішення застосовують усі?
Person
примірників, які все ще не зберігаються, і якщо ідентифікатор вирішено як частина механізму збереження, просто залиште його на нульовому рівні. Що стосується відповіді, JPA використовує номер версії; якщо ви читаєте версію 23, коли ви оновлюєте елемент, якщо версія в БД становить 24, запис не вдається.