java 休眠错误:对象引用未保存的 transient 示例-在刷新之前保存 transient 示例:model.Room

wn9m85ua  于 2023-05-05  发布在  Java
关注(0)|答案(1)|浏览(149)

已解决-已更新

我删除了合并用户方法和添加房间到房间列表从用户。

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示例:

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。

用户

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "users")
public Set<Room> rooms = new HashSet<>();

房间

@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中的保存方法:

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并尝试获取具有OneToMany关联的消息时,会发生错误,因为Room的示例没有在Hibernate上持久化,但它是:

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;
    }

我已经解决了这个问题,但我想使用ORM:

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;
}
k4emjkb1

k4emjkb11#

我不是很确定,我也绝对不是hibernateMaven,但我认为你可以给予一下。

public void save(Room room, User user) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {
            Transaction tx = session.beginTransaction();
            room.getUsers().add(user); //it shouldn't be needed to add the room to the users rooms
            session.merge(room);//the save operation should be cascaded, so the user should be automatically saved as well
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            session.close();
        }
}

相关问题