2

Is there a way to let Hibernate handle removal of an entry in a JoinTable of a @ManyToMany association if I remove an entity that is not managing this association?

As I understand it, if I have a @ManyToMany association like this:

@Entity
public class AlertConfigurationVersion {

    @JoinTable(
                name = SUBJECT_ALERTCONFIGURATION_VERSION_TABLE,
                joinColumns = @JoinColumn(name = "alert_configuration_version_id"),
                inverseJoinColumns = @JoinColumn(name = "subject_id")
    @ManyToMany(cascade = {
                CascadeType.DETACH,
                CascadeType.MERGE,
                CascadeType.REFRESH,
                CascadeType.PERSIST})
    private Set<Subject> subjects = new HashSet<>();
}

Then if I remove an AlertConfigurationVersion, the @ManyToMany table would be correctly updated for any Subjects pointing at it.

But in my case I am removing a Subject (using the standard repository method) and now I get a nasty org.hibernate.exception.ConstraintViolationException with an underlying

org.postgresql.util.PSQLException: ERROR: update or delete on table "subject" violates foreign key constraint "fks123x93urj80014yg4vem4h43" on table "subject_alertconfigurationversion"
  Detail: Key (id)=(9b915613-f37d-45c2-8fd8-8da4f9291aea) is still referenced from table "subject_alertconfigurationversion".

Can I let this case be handled by Hibernate in some way? Ideally NOT by making this association bidirectional as there is no business logic need for that. I don't think that would matter anyway though.

I am using Lombok to generate a hashcode and equals, but I also tried excluding references and/or the id from these based on the advice at https://dev.to/alagrede/why-i-dont-want-use-jpa-anymore-fl and https://developer.jboss.org/wiki/EqualsAndHashCode?_sscc=t

Related: ManyToMany with cascade all only cascading one way, although this is 5 years ago and didn't get much attention, there may be some way now or even then.

Another related question: Hibernate many-to-many cascading delete, I tried the 'hack' in the top answer by duplicating the jointables but this is causing all other kinds of problems and Vlad Mihalcae specifically says (elsewhere) NOT to do this.

Also there is an open issue on Hibernate at https://hibernate.atlassian.net/browse/HHH-12239 that looks like my issue, so it seems it is recognized as a bug, but I'm not 100% sure it applies to my situation. The issue is about bidirectional associations.

Sebastiaan van den Broek
  • 5,818
  • 7
  • 40
  • 73

1 Answers1

1

How can Hibernate remove the associated rows from the SUBJECT_ALERTCONFIGURATION_VERSION_TABLE when the Subject entity has no knowledge of this association?

The only way to address this issue is to use FK-based CASCADE ON DELETE:

ALTER TABLE SUBJECT_ALERTCONFIGURATION_VERSION_TABLE
ADD CONSTRAINT fk_alert_configuration_version_subject_id
FOREIGN KEY (subject_id) REFERENCES subject 
ON DELETE CASCADE
Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
  • Is there a way without needing to directly create an FK on the database? How would it work when giving the Subject entity knowledge of this association? – Roy van der Valk Dec 06 '18 at 12:58
  • Vlad I thought Hibernate would build an in-memory model of the entire domain model of the application, so it would realize that when there is an entity referring the to be deleted entity in a ManyToMany association, it needs to also update that join table when deleting that entity. – Sebastiaan van den Broek Dec 06 '18 at 13:15
  • I am open to the idea of making this a bidirectional association as well if that makes anything easier, but I tried that and it didn’t have any effect with the code I was using then. – Sebastiaan van den Broek Dec 06 '18 at 13:16
  • Due to [HHH-12239](https://hibernate.atlassian.net/browse/HHH-12239), it's better to address this at the DB table-level. Why is it that you don't want to take this approach? – Vlad Mihalcea Dec 06 '18 at 13:21
  • Sorry I totally missed your comment. Doing this at DB level could be an option, I'll discuss it. We'd prefer to let Hibernate manage the whole database though. I read your blog at https://vladmihalcea.com/the-best-way-to-map-a-many-to-many-association-with-extra-columns-when-using-jpa-and-hibernate/ and I suppose we could achieve the same with that by also adding an @OnDelete(action = OnDeleteAction.CASCADE) to the join table entity, but it seems a bit overkill. – Sebastiaan van den Broek Dec 18 '18 at 06:09