repository.save() 如何工作,以及如何在 Spring 数据 JPA 中测试唯一约束

How does repository.save() work, and how to test unique constrains in Spring data JPA

我有一个 table“MyService”,在两列(命名空间和名称)上有唯一约束,Id 是 pk。 |姓名 |类型 | | ------ | -------------- | |编号 |长 | |名称空间 |字符串 | |姓名 |字符串 | |价值 |字符串 |

我想编写单元测试以确保用户不能插入具有相同(命名空间和值)的新行。所以我这样编码:

@Test
public void insertDuplicateTest()  {
    Service service1 = Service.builder().namespace("ns").name("n1").value("v1").build();
    repository.saveAndFlush(service1);
    Service service2 = Service.builder().namespace("ns").name("n1").value("v2").build();
    repository.saveAndFlush(service2);
}

我有两个问题:

  1. 根据我的理解,jparepository 将在实体不存在时插入,如果存在则合并。那么为什么这会引发错误:

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [uk5pg2rvcx3fsu5dctsm3pyqkh6]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

  1. 如何完成此单元测试以检查是否存在错误或异常?

From my understanding jparepository will insert if the entity does not exist, and merge if is. So why this raise an error:

它会,但一个实体存在意味着一个实体具有相同的 主键 存在,其他 columns/attributes 对此并不重要(无论是否唯一) .

当 JPA 尝试插入异常时抛出异常(因为主要不存在)但由于违反了 UNIQUE 约束而失败。

如果您使用 @GeneratedValue 作为主键,它不会合并新创建的对象,而是为它们分配一个新的 ID 并插入它们(由于 UNIQUE 约束而失败)。

如果要合并对象,您需要使用不同的(非@GeneratedValue)主键或修改现有对象(如service1)。

How can I complete this unit test to check there is an error or exception?

如果您希望出现异常,只需使用 assertThrows:

@Test
public void insertDuplicateTest()  {
    Service service1 = Service.builder().namespace("ns").name("n1").value("v1").build();
    repository.saveAndFlush(service1);
    Service service2 = Service.builder().namespace("ns").name("n1").value("v2").build();
    assertThrows(DataIntegrityViolationException.class, () -> repository.saveAndFlush(service2);
}