异常后丢失 EntityManager

Losing EntityManager after Exception

我正在尝试使用异常来处理用户输入的名称超过特定字符数的情况。如果发生异常,我会将其捕获为 PersistenceException 并将信息提供给用户。

    EntityManagerFactory emf=(EntityManagerFactory)getServletContext().getAttribute("emf");
    EntityManager em = emf.createEntityManager();
    try
    {
        String name = request.getParameter("name");
        if(name != null)
        {
            em.getTransaction().begin();
            em.persist(new Guest(name));
            em.getTransaction().commit();
        }
        ...
    }
    catch(PersistenceException e)
    {
        request.setAttribute("valid", false);
    }

但是在通知用户之后,我仍然需要列出之前输入到db的所有名称,但是在以下段中:

    finally
    {
        List<Guest> guests= em.createQuery("SELECT g FROM Guest g",Guest.class).getResultList(); }

我得到:

  org.hibernate.AssertionFailure: null id in com.guest.Guest entry (don't flush the Session after an exception occurs)

当我通过重新创建 entityManager 将 "finally" 部分更改为跟随时,我没有收到错误。

   finally{
        em = emf.createEntityManager();
        List<Guest> guests= em.createQuery("SELECT g FROM Guest....}

我还用 Eclipse 调试器检查了 EntityManager 是否正常,我得到了以下信息:

所以,即使我的 EntityManager 没问题,为什么我需要重新创建它才不会出现该错误?

与您的问题无关,但很明显,您尝试在 finally 子句中执行的 SQL 查询不属于该方法。您正在混合两个 "behaviors".

您可以使用只保存实体的实际方法,然后使用另一个名称更有意义的方法来检索 guests;所以你将不得不调用数据库(就像你现在所做的那样),但你不会有那种奇怪的行为,因为你只是 "separate the concerns".

顺便说一句,该错误可能与您提交(或未提交)更改有关(不确定,只是猜测)并且涉及异常,因此您的 Hibernate 会话可能会丢失。

更新: 查看来自 JB Nizet 的答案。

The documentation清楚了:

If the Session throws an exception, including any SQLException, immediately rollback the database transaction, call Session.close() and discard the Session instance. Certain methods of Session will not leave the session in a consistent state. No exception thrown by Hibernate can be treated as recoverable.