Hibernate的@Version可以考虑相关实体的变化吗?
我有 2 个实体:一对多关系中的父实体和子实体。 Parent
是有版本的,即有一个@Version 字段。我的目标是同步对 Parent
版本上的 Parent
和 Child
实体的更改。
例如,一个线程更新Parent
,另一个线程更新其中一个Child
,这应该会导致 OptimisticLockException。
是否可以?
我尝试向 Child
添加 @PreUpdate ,这会增加其 Parent
的版本,但这没有帮助,因为 Hibernate 似乎仅在检查版本后才执行侦听器,因此无论如何,事务都会成功提交。
如果可以的话,如何实施?
I have 2 entities: Parent
and Child
in a one-to-many relationship. The Parent
is versioned, i.e. has a @Version field. My goal is to synchronize changes to both Parent
and Child
entities on the Parent
's version.
E.g. one thread updates the Parent
and another one updates one of it's Child
s, this should cause an OptimisticLockException.
Is it possible?
I tried adding a @PreUpdate to the Child
which would increment the version of it's Parent
, but that didn't help because Hibernate seems to execute listeners only after it checks versions so the transaction commits successfully anyway.
If it is possible, how can it be implemented?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否尝试将子对象设为组件而不是实体?
默认的 Hibernate 操作可能更符合您的要求。这个想法是,父级是一个真实的实体,而子级被认为是一个更大整体的元素。
在 Hibernate 中,这应该被视为默认的父子关系。
实体之间的父子关系虽然可能,但不太自然。
Did you try making the Child a component instead of an entity?
The default Hibernate operations might be much more aligned with your requirements. The idea is that the Parent is a real entity, while the Child is considered an element of a bigger whole.
In Hibernate, this should be considered the default parent-child relationship.
Parent-Child relation between entities are less natural, although possible.
首先,这里有两个问题需要澄清:
我认为您正在尝试捕获对特定 Child 实例所做的更新而不是集合修改(例如添加新的 Child/删除旧的 Child)。后者将默认增加父级的版本。
当您说“一个线程更新父级”和“另一个线程更新子级”时,我假设更改会立即刷新。换句话说,事件的顺序是:父级更新并持久化(更改刷新;事务提交1);另一个线程尝试更新指向父级的先前版本的子级并失败。如果情况并非如此,乐观锁定不会为您提供帮助。
1 您可以通过设置适当的隔离级别来解决“事务已提交”位,但这可能会导致比在并发环境中解决的问题更多的问题。您无法解决“立即冲洗”的要求。
假设上述假设是正确的,您需要使用 EntityManager.lock() 方法在更新子实例之前锁定父级。请参阅 LockModeType 和 Hibernate EntityManager 文档 了解详细信息。
First of all, there are two issues here that need to be clarified:
I take it you're trying to catch updates made to a particular Child instance rather than collection modifications (e.g. new Child being added / old removed). The latter will increment parent's version by default.
When you say "one thread updates Parent" and "another updates Child" I'm assuming that changes are immediately flushed. In other words, the sequence of events is: parent is updated and persisted (changes flushed; transaction committed1); another thread tries to update child which points to the previous version of parent and fails. If that's not the case, optimistic locking is not going to help you.
1 You may be able to work around the "transaction committed" bit by setting appropriate isolation level, but that's likely to cause more problems then it solves in concurrent environment. You can't work around "immediate flush" requirement.
Assuming the above assumptions are correct, you'll need to use EntityManager.lock() method to lock Parent prior to updating your Child instance. See LockModeType and Hibernate EntityManager docs for details.