IVR Avenger
IVR Avenger

Reputation: 15494

Hibernate OneToMany mapped values not being deleted on threaded actions

I have two @Entity types. One is Document, which contains 1..n pages from PDFs. The other is Tag, which adds context or description to Documents. For example, a Document containing a Bank of America statement might have these tags: BOA, STATEMENT.

The Document @Entity holds Tags as follows:

@Entity(name="document")
public class Document extends TagBearing {

...

@MappedSuperclass
public abstract class TagBearing extends LobMappedEntity {
    
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    protected Set<Tag> tags = new TreeSet<>();

My Spring Boot webapp uses Vaadin, JPA Repositories, and Hibernate. When I manually apply a Tag to a Document, or if I remove a Tag from a Document, I see entries arriving and departing from the generated document_tags table as expected. However, I have a separate app designed to run "headless" and perform expensive tasks on these documents, like OCR of the PDF pages. This "server" app has the same maven dependencies, except for Vaadin.

When this "server" app runs threaded actions, it will load up a document via JpaRepository named query, adjust Tags, and then saveAndFlush. It can ADD a Tag or multiple Tags no problem, provided they are not already present in the Set. Clearing the Set and saving does not cause records to be removed from the table; trying to Save a new Tag in the Set causes an exception as follows: 2024-04-01 20:51:39.466 [Thread-7] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Duplicate entry '781-427' for key 'document_tags.PRIMARY'

So! I assume that some aspect of Hibernate or JPA management is not being passed into these worker threads, so it is therefore not cascading the deletes when I clear the Tags and then do a repository.saveAndFlush(document); However - How do I do this? What else is causing these @OneToMany entries to not be deleted?

Upvotes: -1

Views: 54

Answers (1)

IVR Avenger
IVR Avenger

Reputation: 15494

I had a few problems going on here.

  1. I was updating the documents in an outer loop, not included in the snippet, and I was not refreshing the object after each save. I changed the looping mechanism to save, flush, and then reload the object post-save.

  2. I am storing the Tag entities in a TreeSet, but I did not override equals / hashCode, so the Set was not properly differentiating between new and existing records.

  3. Finally, @OneToMany is the wrong mapping; multiple Documents may have multiple Tags, and changing the annotation to @ManyToMany was required.

All of those changes in place, I can now see entries in the mapping table come and go as operations on the Document object are performed.

Upvotes: 0

Related Questions