Supponiamo che tu abbia un qualche tipo di struttura di dati, che è persistente in un qualche tipo di database. Per semplicità, chiamiamo questa struttura di dati Person. Ora ti viene assegnato il compito di progettare un'API CRUD, che consente ad altre applicazioni di creare, leggere, aggiornare ed eliminare messaggi Person. Per semplicità, supponiamo che questa API sia accessibile tramite un qualche tipo di servizio web.
Per le parti C, R e D di CRUD, il design è semplice. Userò la notazione funzionale simile a C # - l'implementazione potrebbe essere SOAP, REST / JSON o qualcos'altro:
class Person {
string Name;
DateTime? DateOfBirth;
...
}
Identifier CreatePerson(Person);
Person GetPerson(Identifier);
void DeletePerson(Identifier);
Che dire dell'aggiornamento? La cosa naturale da fare sarebbe
void UpdatePerson(Identifier, Person);
ma come specificare quali campi Personaggiornare?
Soluzioni che ho potuto escogitare:
Potresti sempre richiedere il passaggio di una Persona completa , ovvero il cliente farebbe qualcosa del genere per aggiornare la data di nascita:
p = GetPerson(id); p.DateOfBirth = ...; UpdatePerson(id, p);Tuttavia, ciò richiederebbe una sorta di coerenza transazionale o blocco tra Get e Update; in caso contrario, è possibile sovrascrivere alcune altre modifiche apportate in parallelo da un altro client. Ciò renderebbe l'API molto più complicata. Inoltre, è soggetto a errori, poiché il seguente pseudo-codice (presupponendo una lingua client con supporto JSON)
UpdatePerson(id, { "DateOfBirth": "2015-01-01" });- che sembra corretto - non cambierebbe solo DateOfBirth ma ripristinerebbe anche tutti gli altri campi su null.
Potresti ignorare tutti i campi che lo sono
null. Tuttavia, come faresti a fare la differenza tra non cambiarlaDateOfBirthe cambiarla deliberatamente in null ?Cambia la firma in
void UpdatePerson(Identifier, Person, ListOfFieldNamesToUpdate).Cambia la firma in
void UpdatePerson(Identifier, ListOfFieldValuePairs).Utilizzare alcune funzionalità del protocollo di trasmissione: ad esempio, è possibile ignorare tutti i campi non contenuti nella rappresentazione JSON della persona. Tuttavia, ciò di solito richiede di analizzare JSON da soli e di non essere in grado di utilizzare le funzionalità integrate della libreria (ad esempio WCF).
Nessuna delle soluzioni mi sembra davvero elegante. Sicuramente, questo è un problema comune, quindi qual è la soluzione delle migliori pratiche utilizzata da tutti?
Personistanze di nuova creazione che non sono ancora persistenti e nel caso in cui l'identificatore venga deciso come parte del meccanismo di persistenza, lasciarlo a null. Per quanto riguarda la risposta, JPA utilizza un numero di versione; se leggi la versione 23, quando aggiorni l'articolo se la versione nel DB è 24 la scrittura fallisce.