Deleting @ManyToMany parent entity without affecting child on Hibernate

Oh Dear!!

It’s a nightmare getting MySQLIntegrityConstraintViolationException when you’re designing complex relational database structure for your app. Most of the time hibernate won’t complain with your approximation but this won’t work when it comes to bidirectional relations.

Let me show an example.

But first consider a scenario that we’re making a movie database application. We have two entities Movie.java and CustomList.java.

The use case is,

  • User can add multiple movies in a list.
  • And a movie can be added to multiple list.
  • User can execute CRUD operations on their list. that means user can create, edit and delete his list.
  • Admin can delete a Movie.

So it’s a @ManyToMany relationship right?

Okay lets dig into the example.

Our two entities are:

Movie.java

@Entity(name = "movie")
public class Movie extends BaseEntity {
    private String name;
    private String type;
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<CustomList> listOfCustomList;
}

And CustomList.java

@Entity(name = "custom_list")
public class CustomList extends BaseEntity {
    private String title;
    @JsonIgnore
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "listOfCustomList")
    private List<Movie> movieList;
 
}

On Movie entity we’ve a list of CustomList and on CustomList entity we’ve declared a movie list. And there’s a many to many relationship between them. So far so good! But wait, it’s a bidirectional relationship, so we’ve to make one entity parent and the other one child.

We can use mappedby attribute for that. It tells hibernate to map relationship table by the field that was declared on it’s parent entity. There’s one thing to remember that, in which class you’ve used mappedby attribute is NOT the parent.

There’s a problem. One of our user case was deleting a movie, but we don’t want any of the users list to be deleted associated with that movie. Since we made movie a parent, if we delete a movie, all of the lists associated with that movie will be deleted automatically. But we don’t want that. So what can we do?

Yes, you’re probably right. we have to diassociate the CustomList entities first so that deleting a Movie wouldn’t affect any of the list entities.

So write a method on parent entity and annotate it with @PreRemove, and clear the child list of that entity.

 @PreRemove
 private void removeListsFromMovie() {
     getListOfCustomList().clear();
 }

The problem is solved, winter is over.

 

1 thought on “Deleting @ManyToMany parent entity without affecting child on Hibernate

Leave a Reply

Your email address will not be published. Required fields are marked *