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 个不同的线程几乎同时调用时会出现问题。

  1. 计划任务检索旧实体。

  2. rest 端点检索旧实体。

  3. rest 端点执行 child 删除和新的 child 添加。

  4. 其余保存到数据库。

  5. 计划任务将旧 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