简体   繁体   中英

Unique constraint violated on replace item from list in test

So I have client = creditor which has list of documents. This list can contain only one type of each document, so i have method add document which adds new documnet, but if there is already document of this type it should be replaced.

this test fail on unique constraint

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()
}

implementaion is simple replace:

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

above calls:

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

entity:

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

funny is that when I remove unique constraint from flyway test is passing, so it seems like problems with transaction.

I think it might be related to Hibernate's queries ordering during flush time. Because persisting new entities is invoked as first operation by Hibernate's session, you get exception as entity is present in DB during flush time. Turn on show_sql option in Hibernate and try look at logs what is the real order of queries sent to DB.

Also read Vlad's post about ordering: A beginner's guide to Hibernate flush operation order . You can read code of class EventListenerRegistryImpl as well and see how ordering looks like.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM