如何使 Spring boot post api 幂等

Man*_*ish 5 post locking idempotent spring-boot sql-server-2019

我在 Spring boot 应用程序中使用 Spring Data JPA 创建了简单的 CRUD api。控制器中的 Post 方法如下所示:-

@RequestMapping(value = "/article", method = RequestMethod.POST, produces = "application/json")
public Article createArticle(@RequestBody Article article) {
    return service.createArticle(article);
}
Run Code Online (Sandbox Code Playgroud)

服务方法如下:-

@Override
public Article createArticle(Article articleModel) {
    return repository.save(articleModel);
}
Run Code Online (Sandbox Code Playgroud)

我的 JsonPayload 如下所示:

{
   "article_nm":"A1",
   "article_identifier":"unique identifier"
}
Run Code Online (Sandbox Code Playgroud)

现在我想让我的 POST 请求成为幂等的,这样即使我article_identifier再次获得相同的 json 有效负载,它也不会在数据库中创建记录。

我无法在数据库中进行任何方案/约束更改,并且article_identifier字段也不是表中的主键。

我明白,首先我可以检查数据库并返回保存的记录(如果它已经存在),但在这里如果多个请求(原始请求和重复请求)同时出现,两者都会检查数据库并且不会找到具有该标识符的任何记录并将创建 2 条记录(每条一条)。此外,由于它是一个分布式应用程序,我如何保持多个数据库事务之间的一致性。

我怎样才能使用一些锁定机制,这样就不会出现两条相同的记录article_identifier。有人可以建议一些参考如何在 Spring boot 中实现它吗?

Min*_*ius 4

这种情况下需要幂等性来解决回发(或双发请求)。最简单的方法就是在服务级别检查是否存在具有给定信息的帖子(正如您所指出的)。您可以repository.exists()为此使用变体。

我明白,首先我可以检查数据库并返回保存的记录(如果它已经存在)

至于

如果多个请求(原始请求和重复请求)同时出现,两者都会检查数据库,并且不会找到任何具有该标识符的记录,并且会创建 2 条记录(每个记录一条)

如果它是单个数据库,您需要将事务彼此隔离(我知道您说不是,但我正在尝试解释我的推理,所以请耐心等待)。对于那个弹簧有以下注释:@Transactional(isolation = Isolation.SERIALIZABLE)。尽管在这种情况下@Transactional(isolation = Isolation.REPEATABLE_READ) 就足够了。

此外,由于它是一个分布式应用程序,我如何维护多个数据库事务之间的一致性。

它是如何分布的?您首先需要考虑数据库。是主从mysql/postgress/mongodb吗?这是一些奇怪的全球分布式系统吗?假设它是传统的主从设置,那么写事务将由主站处理(据我所知,属于该事务的所有选择也将在那里),所以应该没有问题。然而,只有提供更多细节才能真正给出答案。