java - 测试中列表中的替换项违反了唯一约束

标签 java spring hibernate spring-boot testing

所以我有 client = creditor,它有文件 list 。此列表只能包含每个文档的一种类型,因此我有添加新文档的方法添加文档,但如果已经存在这种类型的文档,则应将其替换。

此测试因唯一约束而失败

def "should replace documents with same type"() {
    given:
        def creditor = creditors.create(CreditorHelper.createSampleCreditorForm())
        def documentType = DocumentTypeEvent.INVESTMENT_INSTRUCTION
    and:
        def old = documents.addDocument(new DocumentForm("urlOld", creditor.creditorReference, documentType, ZonedDateTime.now()))

    when:
        documents.addDocument(new DocumentForm("urlNew", creditor.creditorReference, documentType, ZonedDateTime.now()))

    then:
        def newResult = documentRepository.findByCreditorReference(creditor.creditorReference)
        newResult.size() == 1
        newResult.find {
            it.url == "urlNew"
        }
    and:
        documentRepository.findByHash(old.hash) == Optional.empty()
}

实现很简单替换:

@Transactional
public Document addDocument(final DocumentForm documentForm) {
    return creditorRepository.findByCreditorReferenceIgnoreCase(documentForm.getCreditorReference())
        .addDocument(new Document(documentForm));
}

以上调用:

 public Document addDocument(Document newDocument) {
    documents.removeIf(existingDocument -> existingDocument.getType() == newDocument.getType());
    documents.add(newDocument);
}

实体:

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "creditor_id")
@Builder.Default
private List<Document> documents = new ArrayList<>();

有趣的是,当我从 flyway 测试中删除唯一约束时,它似乎是交易的问题。

最佳答案

我认为这可能与刷新期间 Hibernate 的查询排序有关。因为持久化新实体是 Hibernate session 的第一个操作,所以当实体在刷新期间存在于 DB 中时会出现异常。在 Hibernate 中打开 show_sql 选项并尝试查看日志发送到数据库的查询的真实顺序是什么。

另请阅读 Vlad 关于订购的帖子:A beginner’s guide to Hibernate flush operation order .您也可以阅读类 EventListenerRegistryImpl 的代码,并查看排序方式。

关于java - 测试中列表中的替换项违反了唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56890804/

相关文章:

java - 兼容 JDBC 的主存独立数据库

java - Spring BeanFactoryAware 和 ApplicationContextAware 有什么区别?

java - Spring Autowiring 的成员可见性

java - Hibernate 标准按父级过滤

java - 在Java中存储键值

java - 如何将 chrome 浏览器缩放至 67%,然后单击下一步按钮。?

java - 是否有必要以 root 身份运行 jstack -F(在 Linux 上),如果是,为什么?

Spring boot 从领事服务器获取属性

java - 使用注释向 JPA 或 Hibernate 实体列添加约束

java - @Entity 和 @Table 中的名称属性