Reputation: 1175
I'm trying to delete a user but every row in the database that references the user does NOT get deleted before hibernate tries to remove the user.
I have the same structure for every other entity in the application and it works just fine, all the child rows get deleted first and then the row itself get deleted, but as you see below this is not the case when trying to delete a user. Hibernate goes to this statement :
Hibernate: delete from users where user_id=?
before all comment_votes are deleted. (Posts should also be deleted before as well but I guess the comment_votes error shows up first).
This sequence of sql statements are executed before the error according to the console:
Hibernate: delete from comment_vote where vote_id=?
Hibernate: delete from comment where comment_id=?
Hibernate: delete from comment_vote where vote_id=?
Hibernate: delete from comment where comment_id=?
Hibernate: delete from comment_vote where vote_id=?
Hibernate: delete from comment where comment_id=?
Hibernate: delete from users where user_id=?
This is the error I'm getting:
org.postgresql.util.PSQLException: ERROR: update or delete on table "users" violates foreign key constraint "fkjf73ixvt1jv3wdv4ah0hkpewf" on table "comment_vote"
Detail: Key (user_id)=(2) is still referenced from table "comment_vote".
User.java :
@Entity
@Table(name = "users") // because User is a keyword in some DBs
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id", columnDefinition = "serial")
private Long id;
@NotEmpty
@Column(unique = true)
private String username;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
@JsonIgnore
private List<Post> posts = new ArrayList<>();
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
@JsonIgnore
private List<Comment> comments = new ArrayList<>();
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
@JsonIgnore
private List<CommentVote> comment_votes = new ArrayList<>();
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
@JsonIgnore
private List<PostVote> post_votes = new ArrayList<>();
// getters and setters
}
This is CommentVote.java :
@Entity
@Table(name = "comment_vote")
public class CommentVote {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "vote_id", columnDefinition = "serial")
private Long id;
@Min(value = -1, message = "A vote can not be less than -1")
@Max(value = 1, message = "A vote can not be greater than 1")
@Column(name = "actual_vote")
private int actualVote;
@ManyToOne()
@JoinColumn(name="user_id", nullable=false)
@JsonIgnore
private User user;
// getters and setters
}
I tried with orphanRemoval = true on every child field in User.java but that does not seem to change anything.
Upvotes: 1
Views: 2188
Reputation: 13091
You can try to use @OnDelete
. As it's stated in the documentation:
... the
@OnDelete
cascade is a DDL-level FK feature which allows you to remove a child record whenever the parent row is deleted.So, when annotating the
@ManyToOne
association with@OnDelete(action = OnDeleteAction.CASCADE)
, the automatic schema generator will apply theON DELETE CASCADE
SQL directive to the Foreign Key declaration.
Taken this in mind, you can correct your mapping in the following way:
@Entity
@Table(name = "comment_vote")
public class CommentVote {
// ...
@ManyToOne()
@JoinColumn(name="user_id", nullable=false)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnore
private User user;
// ...
}
Upvotes: 1