Perimosh
Perimosh

Reputation: 2823

Spring JPA Many to Many: remove entity, remove entry in join table, BUT NOT REMOVE the other side

I have this use case:

Users side:

@ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
                    name = "USERS_GROUPS",
                    joinColumns = @JoinColumn(name = "USER_ID", referencedColumnName = "ID") ,
                    inverseJoinColumns = @JoinColumn(name = "GROUP_ID", referencedColumnName = "ID") )
    private List<GroupJPA> groups;

Group side:

@ManyToMany(mappedBy = "groups", cascade = CascadeType.ALL)
private List<UserJPA> returnsList;

If I delete a Group from User's group list, the group gets deleted from User's list, it gets deleted from the join table, and it doesn't get deleted from the Group table. This is the desire behavior.

But, if I delete an entire Group, what happens is, all the references in the join table get deleted, BUT ALSO the Users get deleted as well!! This can not happen.

I'm using 4.3.5.Final and Spring 4.3.0.RELEASE.

Upvotes: 7

Views: 6753

Answers (1)

Alexander Petrov
Alexander Petrov

Reputation: 9492

You need to remove the cascade = CascadeType.ALL from the

@ManyToMany(mappedBy = "groups", cascade = CascadeType.ALL)
private List<UserJPA> returnsList;

The cascading is propagating all operations to the relationship elements. Which means when you delete merge ,persist whatever... These operations are also executed on the UserJPA entities.

Once you remove the group you need to be aware of who is the owner of the preationship. In your case the owner of the relationship is the UserJPA which means that all updates should happen through the owner.

Once the Cascading is removed you need to implement a method on the UserSide which looks like this:

removeFromGroup(Group group) {
    user.getGroups().remove(group);
    groups.removeUser(this);
}

This is in order to ensure that the collections are in sync.

Upvotes: 4

Related Questions