Hibernate瞬态实例异常解决:多对多关联持久化问题
已解决 - 更新内容
我删除了merge User的操作,不再将Room添加到User的rooms列表中。
public void save(Room room, User user) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); try { session.beginTransaction(); room.getUsers().add(user); session.merge(room); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); } finally { session.close(); } }
并在RoomRepository外部更新User实例,以获取最新的User对象:
public void updateUser() { this.user = userRepository.updateUser(user); }
UserRepository中的代码:
public User updateUser(User user) { User result = null; Session session = HibernateUtil.getSessionFactory().getCurrentSession(); try { session.beginTransaction(); result = session.get(User.class, user.getId()); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); } finally { session.close(); } return result; }
这可能不是最佳实践,我需要考虑如何重构这段代码。
问题描述
我有Room和User两个类,它们之间是多对多关联关系。
User类代码
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "users") public Set<Room> rooms = new HashSet<>();
Room类代码
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinTable(name = "sala_usuario", joinColumns = @JoinColumn(name = "id_salas"), inverseJoinColumns = @JoinColumn(name = "cod_user")) private Set<User> users = new HashSet<>();
异常堆栈信息
java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: model.Room at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:161) at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:374) at org.hibernate.query.sqm.internal.QuerySqmImpl.list(QuerySqmImpl.java:1073) at org.hibernate.query.Query.getResultList(Query.java:94) at repository.MessageRepository.findRoomMessages(MessageRepository.java:41) at app.ChatController.loadMessages(ChatController.java:123) at app.ChatController.lambda$initialize$0(ChatController.java:45)
原RoomRepository的save方法
public void save(Room room, User user) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); try { session.beginTransaction(); user.getRooms().add(room); room.getUsers().add(user); session.merge(room); session.merge(user); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); } finally { session.close(); } }
当用户打开Room并尝试通过一对多关联获取消息时触发该异常,尽管Room实例已持久化,但Hibernate仍认为它是瞬态的。
原ORM查询方法
public List<Message> findRoomMessages(Room room) { List<Message> result = null; Session session = HibernateUtil.getSessionFactory().getCurrentSession(); try { session.beginTransaction(); CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaQuery<Message> query = cb.createQuery(Message.class); Root<Message> root = query.from(Message.class); query.select(root).where(cb.equal(root.get("room"), room)); result = session.createQuery(query).getResultList(); session.getTransaction().commit(); } catch (Exception e){ e.printStackTrace(); } finally { session.close(); } return result; }
原生SQL临时解决方法
public List<Message> findRoomMessages(Room room) { List<Message> result = null; Session session = HibernateUtil.getSessionFactory().getCurrentSession(); try { session.beginTransaction(); result = session.createNativeQuery("SELECT * FROM mensajes WHERE id_sala = :pid_sala", Message.class) .setParameter("pid_sala", room.getId()).list(); session.getTransaction().commit(); } catch (Exception e){ e.printStackTrace(); } finally { session.close(); } return result; }
内容的提问来源于stack exchange,提问作者dg0mezm
相关产品推荐
相关产品推荐

