Get Hibernate to delete association before entity

The scenario is this. I have two entities, User and Post for a Twitter-like application. Consider the following

  1. User Alice creates a post.
  2. User Bob favorites the aforementioned post.
  3. User Alice tries to delete the post.

When User Alice tries to delete the post, I get an error from Hibernate;

ERROR: update or delete on table "posts" violates foreign key constraint "fk_jof9iwt9m3lfjxix5ejri4iv9" on table "favorite_posts" Detail: Key (id)=(16) is still referenced from table "favorite_posts".

Code for my entities;

@Table(name = "users")
public class User {
    ...

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Post> posts = new ArrayList<Post>();

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "favorite_posts")
    private Set<Post> favoritePosts = new HashSet<Post>();

    ...
}

@Table(name = "posts")
public class Post {
...
    @ManyToOne
    private User user;
...
}

My alternatives as I see them;

  1. Fetch all of the Users who have favorited a Post, and then clear all of them one by one.
  2. Make the association bidirectional and then clear all of the favorites before deletion.

How can I get Hibernate to delete the association (= the corresponding row in favorite_posts) before trying to delete the entity?

Answers


I'd solve this problem at the database level using ON DELETE CASCADE on the foreign key. It's the simpliest solution, and it doesn't bring extra complexity to the application layer.

However, this approach doesn't play well with your domain model, because your model treats User - Post relationships (both post and favoritePosts) as parts of a User. Therefore, you'll get constraint violation if you try to save a User while one of the Posts it's associated with is being removed.

This can be solved by moving ownership of User - Posts relationships away from User, for example, as follows:

  • User <- Post: you probably would never need all Posts created by a User at once (without filtering or pagination). Therefore it makes no sense to map a relationship from User to Post, unidirectional relationship from Post to User is enough.

  • User <- FavoritePost -> Post: moving "favorite post" relationship to its own entity allows it to have its own lifecycle. Now FavoritePost can silently disappear when associated Post is removed, and it won't create any inconsistency at the application level.


Need Your Help

Cant "get" streams from server

java exception client-server

I am trying to make a simple Client-Server application but when I execute the code I get an exception that the client cannot get the socket's input stream.Please, take a look to my code and try to ...