JPA 和 Hibernate 更新同一实体的某种竞争条件
some kind of a race condition with JPA and Hibernate updating the same entity
我简单说明一下情况,
我有 2 个实体,parent 和 child,在 parent 和 ManyToOne
引用中有 OneToMany
个 child 列表parent 来自 child。我正在级联所有操作,包括从 parent 到 childs.
的孤儿删除
我有一个计划任务每 5 分钟执行一次,检索 parent 实体,执行一些逻辑,更改 child 实体并保存 parent返回数据库。
另外还有一个用于 parent 修改的 REST 端点。首先检查 DB 中是否存在 ID 为 X 的 parent,如果没有 parent,则创建并保存它。否则它检索现有的 parent 删除所有现有的 childs,添加新的 child 并保存 parent返回数据库。
当这 2 个不同的线程几乎同时调用时会出现问题。
计划任务检索旧实体。
rest 端点检索旧实体。
rest 端点执行 child 删除和新的 child 添加。
其余保存到数据库。
计划任务将旧 parent 保存到数据库,并修改旧 child。
我得到的结果是我修改了所有以前的 childs + 新的 child 由 rest 端点插入,而不仅仅是新的 child。我想摆脱旧的 childs.
这种情况很少见,但今年发生了两次,我该如何避免?
使用锁定。看你的需求悲观还是乐观。
乐观
为您的实体添加一个版本字段,例如
@Version
private int version;
悲观
例如使用适当的锁定模式
entityManager.find(Person.class, id, LockModeType.PESSIMISTIC_WRITE);
另请阅读 Hibernate 文档:
https://docs.jboss.org/hibernate/orm/5.5/userguide/html_single/Hibernate_User_Guide.html#locking
我简单说明一下情况,
我有 2 个实体,parent 和 child,在 parent 和 ManyToOne
引用中有 OneToMany
个 child 列表parent 来自 child。我正在级联所有操作,包括从 parent 到 childs.
我有一个计划任务每 5 分钟执行一次,检索 parent 实体,执行一些逻辑,更改 child 实体并保存 parent返回数据库。
另外还有一个用于 parent 修改的 REST 端点。首先检查 DB 中是否存在 ID 为 X 的 parent,如果没有 parent,则创建并保存它。否则它检索现有的 parent 删除所有现有的 childs,添加新的 child 并保存 parent返回数据库。
当这 2 个不同的线程几乎同时调用时会出现问题。
计划任务检索旧实体。
rest 端点检索旧实体。
rest 端点执行 child 删除和新的 child 添加。
其余保存到数据库。
计划任务将旧 parent 保存到数据库,并修改旧 child。
我得到的结果是我修改了所有以前的 childs + 新的 child 由 rest 端点插入,而不仅仅是新的 child。我想摆脱旧的 childs.
这种情况很少见,但今年发生了两次,我该如何避免?
使用锁定。看你的需求悲观还是乐观。
乐观
为您的实体添加一个版本字段,例如
@Version
private int version;
悲观
例如使用适当的锁定模式
entityManager.find(Person.class, id, LockModeType.PESSIMISTIC_WRITE);
另请阅读 Hibernate 文档:
https://docs.jboss.org/hibernate/orm/5.5/userguide/html_single/Hibernate_User_Guide.html#locking