【问题标题】:Race Condition in Postgres SQL using Spring data JpaRepository使用 Spring 数据 Jpa 存储库的 Postgresql 中的竞争条件
【发布时间】:2020-09-03 19:01:21
【问题描述】:

我在使用 Spring 数据 JpaRepository 将数据持久化到 PostgresSQL DB 的实现中遇到了一个奇怪的问题

在我的实体类中,我有以下列:

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private int id;
    
    @Column(name = "field1", nullable = false, length = 16)
    private String field1;

    @Column(name = "field2", nullable = false, length = 16)
    private String field2;

    @Column(name = "field3", nullable = false, length = 16)
    private String field3;

我最初避免将上面的字段声明为复合字段,因为有许多字段要作为复合键处理。我认为 java 代码检查在所有情况下都可以解决问题

所以基本上,我必须根据 field1、field2 和 field3 来保持每一行的唯一性。这是我在我的 java 代码中检查的基本要求,如果数据库中存在任何用于 field1、field2 和 field3 组合的条目,那么我曾经抛出 java 异常

没有两行可以重复这些值。一切都很好,直到应用程序在一些错误的业务场景下进行了测试,这些错误的业务场景在生产中永远不会发生但被错误地运行了

现在发生的情况是,如果在完全相同的实例上触发了 2 个请求,并且上面的 3 个字段完全相同(通过脚本),那么它们都会进入数据库,因为它们都将条目检查为 false

将它们全部声明为一个复合键会解决这种情况吗?

【问题讨论】:

  • 您可以先在 postgres 中添加唯一约束以确保安全

标签: spring spring-data-jpa spring-data


【解决方案1】:

除了 JPA 约束之外,您还应该在数据库中定义唯一约束。

@Entity
@Table(uniqueConstraints={
    @UniqueConstraint(columnNames = {"field1", "field2", "field3"})
}) 
public class MyEntity {
  ...
}

【讨论】:

  • 当然。我会试试这个然后回来。感谢您的帮助
  • 我尝试了上面的建议,它适用于我的集成测试,我在内存数据库中创建 H2,它使用实体定义为集成测试的生命周期创建表。但是,在运行时发布后,uniqueconstraint 在实际表中不起作用。我假设我还必须更改用于创建实际表的 liquibase 脚本。仅将上述内容添加到 Java @Entity 类中是行不通的。如果我错了,请纠正我
猜你喜欢
  • 2012-04-08
  • 2012-06-17
  • 2013-08-12
  • 2014-02-23
  • 1970-01-01
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 2017-04-29
相关资源
最近更新 更多