Ответ
Optimistic Locking — это стратегия управления конкурентным доступом к данным, которая предполагает, что конфликты при одновременном обновлении редки. Вместо физической блокировки записи на уровне БД используется контроль версий.
Реализация через @Version:
@Entity
public class Account {
@Id
private Long id;
private BigDecimal balance;
@Version // Ключевая аннотация
private Long version; // Поле для контроля версии
}
Как работает:
- Чтение: При загрузке сущности JPA сохраняет значение поля
version. - Обновление: При сохранении (
merge/flush) JPA добавляет вWHERE-условие проверку на текущую версию:UPDATE account SET balance=?, version=? WHERE id=? AND version=?; - Конфликт: Если количество обновлённых строк = 0 (значит, версия изменилась другим транзакцией), JPA выбрасывает
OptimisticLockException.
Обработка конфликта:
@Transactional
public void transfer(Long accountId, BigDecimal amount) {
try {
Account acc = accountRepository.findById(accountId).orElseThrow();
acc.withdraw(amount);
accountRepository.save(acc);
} catch (OptimisticLockException e) {
// Стратегия повтора (retry) или уведомление пользователя
throw new ConcurrentModificationException("Данные были изменены. Попробуйте снова.");
}
}
| Плюсы и минусы: | Плюсы | Минусы |
|---|---|---|
| Высокая производительность (нет долгих блокировок) | Требует обработки исключений на уровне приложения | |
| Масштабируемость | Не подходит для сценариев с частыми конфликтами (например, инвентаризация последнего товара) | |
| Избегает взаимных блокировок (deadlocks) |
Альтернатива: Pessimistic Locking (LockModeType.PESSIMISTIC_WRITE), который блокирует запись на уровне БД.