sirve - settitle java
Java-JPA-@Version anotaciĆ³n (5)
Pero aún no estoy seguro de cómo funciona?
Digamos que una entidad MyEntity
tiene una propiedad de version
anotada:
@Entity
public class MyEntity implements Serializable {
@Id
@GeneratedValue
private Long id;
private String name;
@Version
private Long version;
//...
}
En la actualización, el campo anotado con @Version
se incrementará y se agregará a la cláusula WHERE
, algo como esto:
UPDATE MYENTITY SET ..., VERSION = VERSION + 1 WHERE ((ID = ?) AND (VERSION = ?))
Si la cláusula WHERE
no coincide con un registro (porque la misma entidad ya ha sido actualizada por otro hilo), el proveedor de persistencia arrojará una OptimisticLockException
.
¿Significa que deberíamos declarar nuestro campo de versión como final
No, pero podrías considerar proteger al colocador como no se supone que lo llames.
¿Cómo @Version
anotación @Version
en JPA?
Encontré varias respuestas cuyo extracto es el siguiente:
JPA utiliza un campo de versión en sus entidades para detectar modificaciones concurrentes en el mismo registro del almacén de datos. Cuando el tiempo de ejecución de JPA detecta un intento de modificar al mismo tiempo el mismo registro, arroja una excepción a la transacción que intenta cometer el último.
Pero todavía no estoy seguro de cómo funciona.
También a partir de las siguientes líneas:
Debería considerar los campos de versión inmutables. Cambiar el valor del campo tiene resultados indefinidos.
¿Significa que deberíamos declarar nuestro campo de versión como final
?
Aunque la respuesta @Pascal es perfectamente válida, según mi experiencia el siguiente código me resulta útil para lograr el bloqueo optimista:
@Entity
public class MyEntity implements Serializable {
// ...
@Version
@Column(name = "optlock", columnDefinition = "integer DEFAULT 0", nullable = false)
private long version = 0L;
// ...
}
¿Por qué? Porque:
- El bloqueo optimista no funcionará si el campo anotado con
@Version
se configura accidentalmente comonull
. - Como este campo especial no es necesariamente una versión empresarial del objeto, para evitar un error, prefiero
optlock
a ese campo algo así comooptlock
lugar deversion
.
El primer punto no importa si la aplicación usa solo JPA para insertar datos en la base de datos, ya que el proveedor de JPA aplicará 0
para el campo @version
en el momento de la creación. Pero casi siempre las sentencias SQL simples también están en uso (al menos durante las pruebas de unidad / integración).
Cada vez que se actualiza una entidad en la base de datos, el campo de versión se incrementará en uno. Cada operación que actualice la entidad en la base de datos tendrá una WHERE version = VERSION_THAT_WAS_LOADED_FROM_DATABASE
adjunta WHERE version = VERSION_THAT_WAS_LOADED_FROM_DATABASE
en su consulta.
Al verificar las filas afectadas de su operación, el marco jpa puede asegurarse de que no hubo una modificación concurrente entre cargar y persistir su entidad porque la consulta no encontraría su entidad en la base de datos cuando su número de versión se haya incrementado entre carga y persistencia.
Solo agrego un poco más de información.
JPA administra la versión bajo la tapa para usted, sin embargo, no lo hace cuando actualiza su registro a través de JPAUpdateClause()
, en tales casos necesita agregar manualmente el incremento de la versión a la consulta.
Pedro
Versión utilizada para garantizar que solo una actualización en un tiempo. El proveedor de JPA verificará la versión, si la versión esperada ya ha aumentado, entonces otra persona ya actualizará la entidad para que se genere una excepción.
Entonces, actualizar el valor de la entidad sería más seguro, más optimista.
Si el valor cambia con frecuencia, entonces podría considerar no usar el campo de versión. Para un ejemplo "una entidad que tiene un campo de contador, que aumentará cada vez que se acceda a una página web"