Digamos que tiene algún tipo de estructura de datos, que persiste en algún tipo de base de datos. Por simplicidad, llamemos a esta estructura de datos Person
. Ahora tiene la tarea de diseñar una API CRUD, que permite a otras aplicaciones crear, leer, actualizar y eliminar correos electrónicos Person
. Para simplificar, supongamos que se accede a esta API a través de algún tipo de servicio web.
Para las partes C, R y D de CRUD, el diseño es simple. Usaré la notación funcional similar a C #: la implementación podría ser SOAP, REST / JSON u otra cosa:
class Person {
string Name;
DateTime? DateOfBirth;
...
}
Identifier CreatePerson(Person);
Person GetPerson(Identifier);
void DeletePerson(Identifier);
¿Qué hay de la actualización? Lo natural sería
void UpdatePerson(Identifier, Person);
pero, ¿cómo especificaría qué campos Person
actualizar?
Soluciones que podría aportar:
Siempre puede solicitar que se pase una persona completa , es decir, el cliente haría algo como esto para actualizar la fecha de nacimiento:
p = GetPerson(id); p.DateOfBirth = ...; UpdatePerson(id, p);
Sin embargo, eso requeriría algún tipo de consistencia transaccional o bloqueo entre Get y Update; de lo contrario, podría sobrescribir algún otro cambio realizado en paralelo por algún otro cliente. Esto haría que la API sea mucho más complicada. Además, es propenso a errores, ya que el siguiente pseudocódigo (asumiendo un idioma de cliente con soporte JSON)
UpdatePerson(id, { "DateOfBirth": "2015-01-01" });
- que parece correcto - no solo cambiaría DateOfBirth sino que también restablecería todos los demás campos a nulo.
Podrías ignorar todos los campos que están
null
. Sin embargo, ¿cómo haría una diferencia entre no cambiarDateOfBirth
y cambiarlo deliberadamente a nulo ?Cambia la firma a
void UpdatePerson(Identifier, Person, ListOfFieldNamesToUpdate)
.Cambia la firma a
void UpdatePerson(Identifier, ListOfFieldValuePairs)
.Use alguna característica del protocolo de transmisión: por ejemplo, podría ignorar todos los campos que no están contenidos en la representación JSON de la Persona. Sin embargo, eso generalmente requiere analizar el JSON usted mismo y no poder usar las funciones integradas de su biblioteca (por ejemplo, WCF).
Ninguna de las soluciones me parece realmente elegante. Seguramente, este es un problema común, entonces, ¿cuál es la mejor solución utilizada por todos?
Person
instancias recién creadas que aún no son persistentes, y en el caso de que el identificador se decida como parte del mecanismo de persistencia, simplemente déjelo en nulo. En cuanto a la respuesta, JPA usa un número de versión; si lee la versión 23, cuando actualiza el elemento si la versión en DB es 24, la escritura falla.