【发布时间】:2020-10-10 11:38:31
【问题描述】:
我有以下问题
我的服务,它是 Rest 控制器和 JPA 存储库之间的链接,在在数据库中创建实体之前执行一些检查。 但是出现了下面的问题,如果客户端 1 和客户端 2 有一个共同的逻辑父节点,并且同时发送一个创建实体的请求,那么它们很可能同时通过检查,并且能够创建一个实体理论上不应该创建,如何避免这个问题? 此外,如果客户有不同的父级,那么他们可以在任何情况下创建这些实体。
有一个想法是如何解决这个问题,在创建实体之前,必须在创建实体之前获取父行上的锁,然后第二个客户端在尝试创建实体时会出错,但是如何在 Spring JPA 中实现这种方法?谢谢。
为了更好的理解,我举个例子:
public class Parent {
@Id
Long id;
@OneToMany
@JoinColumn(name = "parent_id")
private List<Child> childs;
}
请求创建实体的所有客户端都有一些父级 创建东西的服务和方法的大致代码:
public SomeEntity createSomeEntity(SomeEntity someEntity) {
// further, some checks are made on these lines
// checks
if (checks are passed) {
someEntityRepository.save(someEntity);
} else {
// entity will not be created in the database
}
}
如果客户端有不同的父级,那么没有问题,但如果它们有一个父级,那么假设两个客户端可能同时通过检查并创建冲突的实体。
同时,我不想让这段代码同步或每次都使用悲观锁定创建 SomeEntity,因为对于不同祖先的客户端,多线程会丢失。 正如我所说,我的想法是,如果在签入服务类获取父行上的锁之前,可以解决这个问题,那么我们不会失去并行性以及具有共同父级的客户端创建一个应该不排除,但我不知道如何使用 Spring JPA 来做到这一点
使用 PostgreSQL 数据库版本 12.2
如果我用 SQL 代码来做这件事,在这个地方,我们将 SomeEntity 实体同步添加到客户端,其父级的 id = 1:
START TRANSACTION;
SELECT * FROM parent WHERE id = 1 FOR UPDATE;
-- here is the logic for adding SomeEntity
COMMIT;
【问题讨论】:
-
您要执行的规则是什么?所有孩子都必须有唯一的父母?
-
@KenChan,不,问题是如果客户端有一个共同的父节点,那么你必须阻止他们异步创建 SomeEntity,但是如果他们有 不同父母,然后允许
标签: spring database spring-boot concurrency spring-data-jpa