user3023421 user3023421 - 7 months ago 29
Java Question

Spring JPA OneToMany collection not deleting entry

I am trying to delete an entry from multiple OneToMany relationships, however no matter what I do it does not update the collection.

I have three classes, Rating, Content and User. I can successfully create ratings which properly populates the content and user collections. However, I can not delete ratings from the collections. The rating get successfully deleted, however the content and user collections don't get updated. Below are the three classes:

public class Rating {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;

@ManyToOne(fetch = FetchType.EAGER)
@JsonIdentityInfo(generator = JSOGGenerator.class)
private User user;

@ManyToOne(fetch = FetchType.EAGER)
@JsonIdentityInfo(generator = JSOGGenerator.class)
private Content content;

public void setUser(User user) {
this.user = user;
if (!user.getRatings().contains(this)) {
user.getRatings().add(this);
}
}

public void setContent(Content content) {
this.content = content;
if (!content.getRatings().contains(this)) {
content.getRatings().add(this);
}
}
}

public class User {
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIdentityInfo(generator = JSOGGenerator.class)
private Set<Rating> ratings;

public void addRating(Rating rating) {
this.ratings.add(rating);
if (rating.getUser() != this) {
rating.setUser(this);
}
}

public void removeRating(Rating rating) {
ratings.remove(rating);
}
}

public class Content {
@OneToMany(mappedBy = "content", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIdentityInfo(generator = JSOGGenerator.class)
private Set<Rating> ratings;

public void addRating(Rating rating) {
this.ratings.add(rating);
if (rating.getContent() != this) {
rating.setContent(this);
}
}

public void removeRating(Rating rating) {
ratings.remove(rating);
}
}

public class RatingController {
@RequestMapping(value = "/api/ratings/{id}", method = RequestMethod.DELETE)
public void deleteRating(@PathVariable("id") int ratingId) {
Rating rating = ratingService.getRatingById(ratingId);

if (rating == null) {
return;
}

// THIS DOES NOT DO ANYTHING
rating.getUser().removeRating(rating);

// THIS DOES NOT DO ANYTHING
rating.getContent().removeRating(rating);

ratingService.deleteRating(rating);
}
}


Even when manually removing from the collections it still does not update. Any ideas?

Answer

This looks kind of you have neither a proper hashCode() and equals() method for your Rating class. Java can't find the one you want to delete and thus it's not getting removed.

You could write an EntityBase from which all the classes will have this common code:

@Override
public boolean equals(Object obj) {
    if (obj == null || !this.getClass().equals(obj.getClass())) {
        return false;
    }
    return ComparisonChain.start().compare(getId(), ((EntityBase) obj).getId()).result() == 0;
}

@Override
public int hashCode() {
    return (getId() == null) ? super.hashCode() : getId().intValue();
}

See also: