How to Remove Entity with Manytomany Relationship in JPA (And Corresponding Join Table Rows)

How to remove entity with ManyToMany relationship in JPA (and corresponding join table rows)?

  • The ownership of the relation is determined by where you place the 'mappedBy' attribute to the annotation. The entity you put 'mappedBy' is the one which is NOT the owner. There's no chance for both sides to be owners. If you don't have a 'delete user' use-case you could simply move the ownership to the Group entity, as currently the User is the owner.
  • On the other hand, you haven't been asking about it, but one thing worth to know. The groups and users are not combined with each other. I mean, after deleting User1 instance from Group1.users, the User1.groups collections is not changed automatically (which is quite surprising for me),
  • All in all, I would suggest you decide who is the owner. Let say the User is the owner. Then when deleting a user the relation user-group will be updated automatically. But when deleting a group you have to take care of deleting the relation yourself like this:

entityManager.remove(group)
for (User user : group.users) {
user.groups.remove(group);
}
...
// then merge() and flush()

Spring Data Jpa - ManyToMany - delete entities of the join table

Cascade Remove in a manyToMany it's not only applied to the link table, but to the other side of the association as well.

So Cascade.ALL which inherit remove too is almost always a bad thing to have on a manyToMany as it ends up deleting things not only from association table.

What you want is to have add and remove method in your entities to do the work and keep both list synchronized:

public class ClassA extends [...] implements [...] {
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(name = JOIN_TABLE_NAME,
joinColumns = @JoinColumn(name = COLUMN_REF_A, referencedColumnName = COLUMN_ID_A),
inverseJoinColumns = @JoinColumn(name = COLUMN_REF_B, referencedColumnName = COLUMN_ID_B))
private List<ClassB> fieldClassB;

public void addClassB(ClassB b) {
fieldClassB.add(b);
b.fieldClassA().add(this);
}

public void removeClassB(ClassB b) {
fieldClassB.remove(b);
b.fieldClassA().remove(this);
}
}

Remove the first entity and its relationship without removing the second entity - Spring Data JPA

I solved my issue like this, I'm not sure if this is a best approach to solve this:

public void removeUser(Long id) {
Optional<UsersEntity> userById = usersRepository.findById(id);
if (userById.isPresent()) {
UsersEntity user = userById.get();
for (RolesEntity role : user.getRoles()) {
role.setUsers(null);
rolesRepository.save(role);
}
usersRepository.delete(user);
} else {
throw new IllegalArgumentException("User not found!");
}
}

How should I remove data from Join table in JPA

That's because you are using entityManager.remove. That command will delete a student and all the books associated to it because of the cascade.

If you only want to remove a book from the association,the returnBook method should look something like this:

@Transactional
public void returnBook(Student student, Books book) {
try {
if(student !=null && book !=null) {
Student entityStudent = entityManager.getReference( Student.class, student.getId())
Book entityBook = entityManager.getReference( Book.class, book.getId())
entityStudent.removeBook(entityBook);
}
}
...
}

Changes will be propagated to the db during commit or the flush of the session.

Note that I've added the getReference() calls because I don't know if student and book are managed entities. If they are, it's not necessary to use getReference().

Assuming that this is what removeBook looks like:

    public void removeBook(Book book) {
this.books.remove( book );
book.getStudents().remove( this );
}

As described in the Hibernate ORM documentation, it's important to update both side of the association.

Also the mapping of the association on one of the entities should be:

@ManyToMany(mappedBy = "...")

You should decide which entity owns the association.

By the way, are you sure the mapping you are trying to achieve is not the one described in the Hibernate ORM documentation as Example 172. Bidirectional many-to-many with link entity?

Spring JPA and remove entries from @ManyToMany

I appear to have solved this using @PreRemove, as noted in https://stackoverflow.com/a/14911910/1041691

e.g.
https://github.com/fommil/zibaldone/blob/master/src/main/java/com/github/fommil/zibaldone/Note.java#L74

how to stop Hibernate/JPA from deleting join table records when I update entity in ManyToMany relationship?

Why are two distinct associations (User.projects and Project.users) mapped to the same join table?

If you want a bidirectional association, only one of the sides should be the owning side, the other side should be mapped with mappedBy. Using mappedBy for the User.projects side will solve your problem, by the way.



Related Topics



Leave a reply



Submit