Зачем нужна @Version в JPA

Ответ

Аннотация @Version в JPA используется для оптимистичной блокировки (optimistic locking). Она помогает предотвратить конфликты при одновременном изменении одной и той же сущности разными транзакциями.

Принцип работы:

  1. Поле с @Version автоматически увеличивается при каждом обновлении сущности
  2. Если две транзакции пытаются изменить одну запись, но имеют разное значение версии, выбрасывается OptimisticLockException

Пример:

@Entity
public class Product {
    @Id
    private Long id;

    @Version
    private Long version;

    // другие поля
}

Преимущества:

  • Не блокирует данные на уровне БД
  • Простота реализации
  • Подходит для высоконагруженных систем

Используется обычно с числовыми полями (Long, Integer) или с Timestamp.

Ответ 18+ 🔞

А, ну это про ту самую аннотацию, которая как будто говорит: «Эй, пока ты тут свой SQL писал, кто-то уже успел эту запись обоссать!»

В общем, @Version — это такая хитрая жопа для оптимистичной блокировки. Представь: два потока лезут в одну и ту же сущность, как мартышки на банан. Без версии они бы друг другу нахуй всё перезаписали и даже не заметили. А с версией — начинается цирк.

Как это, блядь, работает:

  1. Вешаешь @Version на какое-нибудь числовое поле (обычно Long или Integer). Это как татуировка «не трожь, моё».
  2. Когда сущность впервые сохраняется, Hibernate ставит там, скажем, 0.
  3. Потом, когда ты её обновляешь, он автоматом, сука, увеличивает версию на единицу перед запросом UPDATE.
  4. И самый сок: этот UPDATE в БД выглядит не просто UPDATE product SET name = 'Шляпа' WHERE id = 5, а UPDATE product SET name = 'Шляпа', version = 1 WHERE id = 5 AND version = 0.
  5. И вот если второй поток уже успел обновить запись и сдвинул версию, то условие WHERE не сработает — обновлено будет 0 строк. JPA это видит и орет: «Оп-па!» — швыряя тебе в рожу OptimisticLockException.

Вот тебе пример кода, чтоб глаза не разбегались:

@Entity
public class Product {
    @Id
    private Long id;

    @Version
    private Long version; // Вот этот самый сторожевой хуй

    private String name;
    // ... остальные поля
}

Плюсы всей этой движухи:

  • Не блокирует БД наглухо. Никаких SELECT FOR UPDATE, которые всё тормозят. Просто проверка версии и пошёл дальше.
  • Проще пареной репы. Написал одну аннотацию — и защита от дурака (точнее, от другого такого же потока) готова.
  • Для нагрузки подходит. Когда запросов овердохуища, а конфликты редки — это то, что надо.

Используют обычно для числовых полей, но можно и Timestamp прикрутить, хотя с ним, блядь, мороки больше из-за точности времени. Короче, @Version — это как поставить на свою пивную кружку в баре замызганную бумажку с надписью «Не пить!». Работает, пока все адекватные.