I have a confusing problem which I haven't figured out how to solve. if you can offer a suggestion of how I can fix my problem I would be grateful.
So I have the following entity relationship model here.
The mapping of User.class is:
@Entity
@Table(name = "CRM_USER")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "USER_ID")
private Long id;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "LAST_NAME")
private String lastName;
@Column(name = "BIRTHDATE")
private Date birthDate;
@Column(name = "EMAIL")
private String email;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private UserAdditionalInfo additionalInfo;
@ManyToOne
@JoinColumn(name = "TEAM_FK")
private Team team;
@ManyToOne
@JoinColumn(name = "JOB_FK")
private Job job;
@ManyToOne
@JoinColumn(name = "ORGANIZATION_FK", nullable = false)
private Organization organization;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private Security security;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "INFO_FILE_FK")
private InfoFile profilePicture;
@ManyToOne
@JoinColumn(name = "COUNTRY_FK")
private Country country;
// Getters and Setters
}
The mapping of Comment.class is:
@Entity
@Table(name = "CRM_COMMENT")
public class Comment implements Serializable {
private static final long serialVersionUID = -104145851368148154L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "COMMENT_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "ARTICLE_ID")
private Article article;
@ManyToOne
@JoinColumn(name = "USER_FK", nullable = false)
private User createdUser;
@Column(nullable = false)
private String comment;
@Column(name = "CREATION_DATE", nullable = false)
private Date creationDate;
@Column(name = "MODIFICATION_DATE")
private Date modificationDate;
@OneToMany(cascade = {CascadeType.ALL}, orphanRemoval = true)
@JoinTable(name = "CRM_COMMENT_LIKE",
joinColumns = {@JoinColumn(name = "COMMENT_ID")},
inverseJoinColumns = {@JoinColumn(name = "USER_ID")})
private Set<User> fans = new LinkedHashSet<>();
// Getters and Setters
}
The mapping of Article.class is:
@Entity
@Table(name = "CRM_ARTICLE")
public class Article implements Serializable {
// other properties
@OneToMany(mappedBy = "article", cascade = {CascadeType.ALL}, orphanRemoval = true)
@OrderBy("id DESC")
private Set<Comment> comments = new LinkedHashSet<>();
// Getters and Setters
}
The problem is related to my ManyToMany relation between the Comment and User - CRM_COMMENT_LIKE.
Actually, when I add some new 'fan' into Comment, there is no problem.
@Override
public boolean giveAnLikeToComment(Long commentId, User fan) {
Comment comment = commentDao.get(commentId);
if (Objects.isNull(comment)|| BooleanUtils.isTrue(comment.getFans().contains(fan))) {
return false;
}
comment.getFans().add(fan);
commentDao.update(comment);
return true;
}
The problem arises when I try to delete some comment, which has at least one 'like'/'fan' to it.
@Override
public boolean deleteCommentById(final Long commentId) {
Comment comment = commentDao.get(commentId);
if (Objects.nonNull(comment)) {
Article article = comment.getArticle();
article.getComments().remove(comment);
comment.setFans(null); // This line fix the problem
articleDao.update(article);
return true;
}
return false;
}
So in this case, I manage the relation between an Article ( which is parent of a Comment) and the comment itself. This is easy, because the connection between them is bidirectional. But what about the fans? I can't remove the connection between a Comment and CRM_COMMENT_LIKE relation, because the User doesn't know about the CRM_COMMENT_LIKE or about the Comments. Something more, I want, when I remove a Comment, to remove and all created relations in CRM_COMMENT_LIKE. But I'm prevent, because Hibernate throws an exception which says:
deleted object would be re-saved by cascade (remove deleted object from associations): [crm.alltogether.core.admin.model.User#1]; nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [crm.alltogether.core.admin.model.User#1]
This is my issue, so if you have a suggestion, I would be glad to read it :)
Best Regards,
You need to have a orphanRemoval=true
cascading between Article
and Comment
. Then you would do this.
if (Objects.nonNull(comment)) {
Article a = comment.getArticle();
a.getComments().remove(comment);
articleDao.saveOrUpdate(a);
return true;
}
This will take care of deleting orphan comment, as you already have a cascade all on fans
it would delete that association as well. I would suggest you to play around with cascade orphanRemoval=true
on fans
as well.