Может ли @Version Hibernate рассмотреть изменения в связанных объектах?

У меня есть 2 лица: Parent а также Child в отношениях один ко многим. Parent является версионным, то есть имеет поле @Version. Моя цель - синхронизировать изменения обоих Parent а также Child юридические лица на Parentверсия

Например, один поток обновляет Parent а другой обновляет один из его Childs, это должно вызвать исключение OptimisticLockException.

Является ли это возможным?

Я попытался добавить @PreUpdate к Child который будет увеличивать версию этого Parent, но это не помогло, потому что Hibernate, похоже, выполняет слушатели только после того, как проверит версии, поэтому транзакция все равно будет успешно зафиксирована.

Если это возможно, как это можно реализовать?

2 ответа

Вы пытались сделать Child компонентом вместо сущности?

Операции Hibernate по умолчанию могут быть в большей степени согласованы с вашими требованиями. Идея состоит в том, что Родитель - это реальная сущность, а Ребенок считается элементом большего целого.

В Hibernate это должно рассматриваться как отношение родитель-ребенок по умолчанию. Родительско-дочерние отношения между сущностями менее естественны, хотя и возможны.

Прежде всего, здесь есть два вопроса, которые необходимо прояснить:

  1. Я полагаю, вы пытаетесь отловить обновления, сделанные для определенного экземпляра дочернего элемента, а не изменения коллекции (например, добавляется новый дочерний элемент / удаляется старый) Последний будет увеличивать версию родителя по умолчанию.

  2. Когда вы говорите "один поток обновляет родительский", а "другой поток обновляет дочерний", я предполагаю, что изменения немедленно сбрасываются. Другими словами, последовательность событий: родитель обновляется и сохраняется (изменения сброшены; транзакция зафиксирована1); другой поток пытается обновить дочерний элемент, который указывает на предыдущую версию parent, и завершается неудачно. Если это не так, оптимистичная блокировка не поможет вам.

1 Возможно, вам удастся обойти бит "фиксация транзакции", установив соответствующий уровень изоляции, но это, вероятно, вызовет больше проблем, чем решает в параллельной среде. Вы не можете обойти требование "немедленного сброса".

Предполагая, что приведенные выше предположения верны, вам нужно использовать метод EntityManager.lock() для блокировки Parent до обновления вашего экземпляра Child. Подробности смотрите в документах LockModeType и Hibernate EntityManager.

Другие вопросы по тегам