I am trying to understand the principles of ManyToMany relations in Hibernate. I've created a small test project and the question is:
I want "Managers" to be saving in db when the "User" is saving. So Manager entity is dependent on User.
When I am saving user1 - everything is fine. I am getting user1 and manager1 and manager3 saved to db. But on the next row where I am trying to save user2 to db I am getting an Exception:
Converting org.hibernate.PersistentObjectException
to JPA PersistenceException
: detached entity passed to persist: ua.testing.entities.Manager
I think the problem is because I am trying to save user2 which contains manager1, which was saved in db in previous row. But how can I avoid this problem and make everything work?
User entity:
package ua.testing.entities;
import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(cascade = CascadeType.ALL)
private List<Manager> managerList = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Manager> getManagerList() {
return managerList;
}
public void setManagerList(List<Manager> managerList) {
this.managerList = managerList;
}
}
Manager entity:
package ua.testing.entities;
import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "manager")
public class Manager {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(mappedBy = "managerList")
private List<User> userList = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}
Main method:
package ua.testing;
import ua.testing.dao.UserDao;
import ua.testing.entities.*;
public class App
{
public static void main( String[] args )
{
User user1 = new User();
User user2 = new User();
User user3 = new User();
Manager manager1 = new Manager();
Manager manager2 = new Manager();
Manager manager3 = new Manager();
manager1.getUserList().add(user1);
manager1.getUserList().add(user2);
manager2.getUserList().add(user1);
manager2.getUserList().add(user3);
manager3.getUserList().add(user2);
manager3.getUserList().add(user3);
user1.getManagerList().add(manager1);
user1.getManagerList().add(manager3);
user2.getManagerList().add(manager1);
user2.getManagerList().add(manager2);
user3.getManagerList().add(manager2);
user3.getManagerList().add(manager3);
UserDao userDao = new UserDao();
userDao.persist(user1);
userDao.persist(user2); // EXCEPTION HERE
}
}
Exception I am getting:
Exception in thread "main" jakarta.persistence.PersistenceException: Converting `org.hibernate.PersistentObjectException` to JPA `PersistenceException` : detached entity passed to persist: ua.testing.entities.Manager
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:165)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:175)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:182)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:783)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:725)
at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:299)
at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:289)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:511)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:432)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:545)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:475)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:435)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:151)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:474)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:122)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:184)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:129)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:53)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:735)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:719)
at ua.testing.dao.UserDao.persist(UserDao.java:13)
at ua.testing.App.main(App.java:34)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: ua.testing.entities.Manager
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:121)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:777)
... 23 more