持久化重复行时的 Javax 唯一约束行为

标签 java postgresql hibernate spring-boot spring-data

假设我在 Postgresql 数据库中有一个表:

CREATE TABLE FOO (
   ID INT PRIMARY KEY      NOT NULL,
   NAME           CHAR(50) UNIQUE NOT NULL
);

它是由 Hibernate 在 Spring Boot 应用程序中创建的

我想插入以下内容:

INSERT INTO FOO (ID, NAME) VALUES (1, "BAR");
INSERT INTO FOO (ID, NAME) VALUES (2, "BAZ");
INSERT INTO FOO (ID, NAME) VALUES (3, "ZIP");

作为以下类中的种子数据:

@Component
public class SeedDB implements CommandLineRunner {

  private final FooRepository fooRepository;

  @Autowired
  public SeedDB(FooRepository fooRepository) {
    this.fooRepository = fooRepository;
  }

  @Override
  public void run(String... strings) throws Exception {
    fooRepository.save(new Foo("bar"));
    fooRepository.save(new Foo("baz"));
    fooRepository.save(new Foo("zip"));
  }
}

所有这一切只是为了说明,只要数据库是空的,这个方法就很好用。但如果将其设置为每次应用程序启动时运行,则唯一约束会导致以下错误:

Caused by: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [ukjsk1parw92chjvhsj49tl7492]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "ukjsk1parw92chjvhsj49tl7492"
Detail: Key (name)=(bar) already exists.

我想这是有道理的。我想弄清楚是否有一种方法,无需将每一行包装在 if/else 或 try/catch block 中,即可尝试插入而不考虑结果?

问题是我无法使用创建删除 hibernate 方法,因为模式中还有其他表不能丢失。

最佳答案

您可以在这里使用try catch block ,但我认为如果唯一字段,我们应该每次在数据库中检查(字段存在与否),然后再持久化我们的实体,因此它将返回它的保证,我认为这是更好的方法,因为在 try catch 的情况下,如果我们将处理 ConstraintViolationException(Implementation of JDBCException 表明请求的 DML操作导致违反定义的完整性约束。),这种异常可能发生在任何导致违反 DML 操作的情况,因此最好确保我们的归档是唯一的,我们需要在持久之前检查它,如果存在实体,我们可以向用户或日志显示用户友好的消息。

在你的情况下,代码会像:

if(fooRepository.countByFiledName("bar")==0) {
 fooRepository.save(new Foo("bar"));
}

关于持久化重复行时的 Javax 唯一约束行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43577979/

相关文章:

Hibernate多对多: Criteria for looking up all class A which contains class B

java - 使用相同的 Android 应用程序作为新应用程序的基础

JavaFX计时器线程问题

使用 PostgreSQL 对多边形中的点进行 SQL 查询

java - 将 Postgresql 查询转换为 Hibernate

java - 使用纯 Hibernate ORM 的 SpringBoot 配置,无需 JPA

java - 关于synchronized关键字如何处理锁和线程饥饿的问题

java - Hibernate和Mysql,事务自动提交只是一个部分

database - 如何在 TablePlus 中创建数据库

java - 将 Spring Boot 与现有 Spring 应用程序集成