我正在尝试使用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是否正常,我得到了以下内容:
所以,即使我的EntityManager也没问题,为什么我需要再次创建它才能没有错误?
答案 0 :(得分:2)
如果Session抛出异常(包括任何SQLException),则立即回滚数据库事务,调用Session.close()并丢弃Session实例。 Session的某些方法不会使会话保持一致状态。 Hibernate抛出的异常不能被视为可恢复的。
答案 1 :(得分:0)
与您的问题无关,但显然您尝试在finally
子句中执行的SQL查询不属于该方法。你混合了两个“行为”。
您可以使用实际方法仅保存实体,然后使用另一个具有更有意义名称的方法来检索guests
;所以你必须进行数据库调用(就像你现在一样),但你不会有那种奇怪的行为,因为你只是“分开了关注点”。
更新:请参阅 JB Nizet 的答案。