异常后丢失EntityManager

时间:2015-08-13 20:02:38

标签: java hibernate exception jpa entitymanager

我正在尝试使用Exceptions来处理用户输入的名称长于特定数量字符的情况。如果发生异常,我将其作为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是否正常,我得到了以下内容:

enter image description here

所以,即使我的EntityManager也没问题,为什么我需要再次创建它才能没有错误?

2 个答案:

答案 0 :(得分:2)

The documentation很清楚:

  

如果Session抛出异常(包括任何SQLException),则立即回滚数据库事务,调用Session.close()并丢弃Session实例。 Session的某些方法不会使会话保持一致状态。 Hibernate抛出的异常不能被视为可恢复的。

答案 1 :(得分:0)

与您的问题无关,但显然您尝试在finally子句中执行的SQL查询不属于该方法。你混合了两个“行为”。

您可以使用实际方法仅保存实体,然后使用另一个具有更有意义名称的方法来检索guests;所以你必须进行数据库调用(就像你现在一样),但你不会有那种奇怪的行为,因为你只是“分开了关注点”。

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

更新:请参阅 JB Nizet 的答案。