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 theUser
is the owner. - On the other hand, you haven't been asking about it, but one thing worth to know. The
groups
andusers
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
How to Select/Get Drop Down Option in Selenium 2
How to Annotate MySQL Autoincrement Field with JPA Annotations
How Should Equals and Hashcode Be Implemented When Using JPA and Hibernate
Base64 Java Encode and Decode a String
Behaviour of Final Static Method
Differencebetween Jvm, Jdk, Jre & Openjdk
What Is the Maven-Shade-Plugin Used For, and Why Would You Want to Relocate Java Packages
Difference Between Each Instance of Servlet and Each Thread of Servlet in Servlets
How to Perform String Diffs in Java
How to Create a Linked List Data Structure in Java
Java Garbage Collection Log Messages
How to Create a Multidimensional Arraylist in Java
How to Do Arithmetic Operations on the Number Baseclass