Как делает @Version
работа аннотации в JPA?
Я нашел различные ответы, извлечение которых следующие:
JPA использует поле версии в Ваших объектах для обнаружения параллельных модификаций к той же записи хранилища данных. Когда время выполнения JPA обнаруживает попытку одновременно изменить ту же запись, оно выдает исключение к транзакции, пытающейся фиксировать в последний раз.
Но я все еще не уверен, как это работает.
Также как от следующих строк:
Необходимо считать поля версии неизменными. Изменение значения поля имеет неопределенные результаты.
Это означает, что мы должны объявить наше поле версии как final
?
Но я все еще не уверен, как это работает?
Допустим, у объекта MyEntity
есть аннотированная версия
:
@Entity
public class MyEntity implements Serializable {
@Id
@GeneratedValue
private Long id;
private String name;
@Version
private Long version;
//...
}
При обновлении поле, помеченное @Version
, будет увеличено и добавлено в предложение WHERE
, примерно так:
UPDATE MYENTITY SET ..., VERSION = VERSION + 1 WHERE ((ID = ?) AND (VERSION = ?))
Если Предложение WHERE
не соответствует записи (поскольку тот же объект уже был обновлен другим потоком), тогда поставщик сохраняемости выдаст исключение OptimisticLockException
.
Означает ли это, что мы должны объявить наше поле версии как final
Нет, но вы могли бы подумать о том, чтобы сделать установщик защищенным, поскольку вы не должны его называть.
Каждый раз, когда объект обновляется в базе данных, поле версии увеличивается на единицу. Каждая операция, которая обновляет объект в базе данных, будет добавлять к своему запросу WHERE version = VERSION_THAT_WAS_LOADED_FROM_DATABASE
.
При проверке затронутых строк вашей операции инфраструктура jpa может убедиться, что не было одновременных изменений между загрузкой и сохранением вашей сущности, потому что запрос не нашел бы вашу сущность в базе данных, когда номер версии был увеличен между загрузкой и сохранением.