如何在 Postgres 和 H2 中处理同一事务中的插入和删除而不发生唯一索引冲突?

发布于 2025-01-10 01:33:11 字数 1901 浏览 1 评论 0原文

我有一个 Spring Boot 项目,其中有一个用于生产的 postgreSQL 数据库和一个用于测试的 h2 数据库。我正在通过 JpaRepository::save 更新嵌套对象。该对象保存其组件的列表,每个组件都有自己的 id 和一个在 SQL 模式中定义的唯一约束下的值。以下是精简版本:

@Entity
class Class {
  @Id
  int id

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "class", orphanRemoval = true, cascade = { CascadeType.ALL })
  List<Pupil> pupils;
}

@Entity
class Pupil {
  @Id
  int id

  int bookId;
}

我可能会更新现有的 Class 4567,其中唯一值已更改,例如删除了 pupil 1 并添加了新的 pupil 21 添加了之前由学生 1 持有的书 8486。由于唯一约束仍然有效,我希望 jpa 能够毫无问题地执行更新,因为“后状态”有效。 然而,情况并非如此,而是根据

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PUPIL_UNIQUE_INDEX_4 ON PUBLIC.PUPIL(CLASS_ID, BOOK_ID) VALUES (4567, 8486)"; SQL statement:
insert into PUPIL (PUPIL_ID, BOOK_ID) values (?, ?) [23505-191]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PUPIL_UNIQUE_INDEX_4 ON PUBLIC.PUPIL(CLASS_ID, BOOK_ID) VALUES (4567, 8486)"; SQL statement:
insert into PUPIL (PUPIL_ID, BOOK_ID) values (?, ?) [23505-191]];
...

这篇文章: https://mossgreen.github.io/JPA-parent-children-updating-violates-constraint/ JPA实际上并没有意识到之后的状态将是有效的,但先插入然后已经抱怨。该帖子建议将 DEFERRABLE INITIALLY DEFERRED 添加到唯一约束中,但是尽管我有 application.properties,但这在 h2 上不起作用:

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect

我不想丢失 bookId 我不能仅仅删除 h2 作为测试数据库。我怎样才能在一个 JpaRepository::save 中进行插入和删除工作?

I have a spring boot project with a postgreSQL database in production and an h2 database for testing. I am updating a nested object via JpaRepository::save. The object holds a list of its components who each have their own id and a value under a unique constraint, defined in the SQL schema. Below is a condensed version:

@Entity
class Class {
  @Id
  int id

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "class", orphanRemoval = true, cascade = { CascadeType.ALL })
  List<Pupil> pupils;
}

@Entity
class Pupil {
  @Id
  int id

  int bookId;
}

It can happen that I update an existing Class 4567 where the unique values have changed, e.g. pupil 1 is removed and a new pupil 21 is added with book 8486 which was previously held by pupil 1. As the unique constraint is still valid I expect jpa to execute the update without issues as the "after state" is valid.
However, this is not the case, instead I get

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PUPIL_UNIQUE_INDEX_4 ON PUBLIC.PUPIL(CLASS_ID, BOOK_ID) VALUES (4567, 8486)"; SQL statement:
insert into PUPIL (PUPIL_ID, BOOK_ID) values (?, ?) [23505-191]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PUPIL_UNIQUE_INDEX_4 ON PUBLIC.PUPIL(CLASS_ID, BOOK_ID) VALUES (4567, 8486)"; SQL statement:
insert into PUPIL (PUPIL_ID, BOOK_ID) values (?, ?) [23505-191]];
...

According to this post: https://mossgreen.github.io/JPA-parent-children-updating-violates-constraint/ JPA does not in fact realize that the after state will be valid but inserts first and then already complains. The post reccomends adding DEFERRABLE INITIALLY DEFERRED to the unique constraint, however that doesn't work on h2 despite my application.properties:

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect

I do not want to lose the unique constraint on bookId and I cannot just drop h2 as a test database. How can I still make inserts and deletions in one JpaRepository::save work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文