Может ли @Version Hibernate рассмотреть изменения в связанных объектах?
У меня есть 2 лица: Parent
а также Child
в отношениях один ко многим. Parent
является версионным, то есть имеет поле @Version. Моя цель - синхронизировать изменения обоих Parent
а также Child
юридические лица на Parent
версия
Например, один поток обновляет Parent
а другой обновляет один из его Child
s, это должно вызвать исключение OptimisticLockException.
Является ли это возможным?
Я попытался добавить @PreUpdate к Child
который будет увеличивать версию этого Parent
, но это не помогло, потому что Hibernate, похоже, выполняет слушатели только после того, как проверит версии, поэтому транзакция все равно будет успешно зафиксирована.
Если это возможно, как это можно реализовать?
2 ответа
Вы пытались сделать Child компонентом вместо сущности?
Операции Hibernate по умолчанию могут быть в большей степени согласованы с вашими требованиями. Идея состоит в том, что Родитель - это реальная сущность, а Ребенок считается элементом большего целого.
В Hibernate это должно рассматриваться как отношение родитель-ребенок по умолчанию. Родительско-дочерние отношения между сущностями менее естественны, хотя и возможны.
Прежде всего, здесь есть два вопроса, которые необходимо прояснить:
Я полагаю, вы пытаетесь отловить обновления, сделанные для определенного экземпляра дочернего элемента, а не изменения коллекции (например, добавляется новый дочерний элемент / удаляется старый) Последний будет увеличивать версию родителя по умолчанию.
Когда вы говорите "один поток обновляет родительский", а "другой поток обновляет дочерний", я предполагаю, что изменения немедленно сбрасываются. Другими словами, последовательность событий: родитель обновляется и сохраняется (изменения сброшены; транзакция зафиксирована1); другой поток пытается обновить дочерний элемент, который указывает на предыдущую версию parent, и завершается неудачно. Если это не так, оптимистичная блокировка не поможет вам.
1 Возможно, вам удастся обойти бит "фиксация транзакции", установив соответствующий уровень изоляции, но это, вероятно, вызовет больше проблем, чем решает в параллельной среде. Вы не можете обойти требование "немедленного сброса".
Предполагая, что приведенные выше предположения верны, вам нужно использовать метод EntityManager.lock() для блокировки Parent до обновления вашего экземпляра Child. Подробности смотрите в документах LockModeType и Hibernate EntityManager.