2012-02-24 67 views
6

您好我有以下功能的简单的DAO()导致对象出现分离。JPA EntityManager的坚持,即使被抛出一个错误

public element createElement(Element e){ 

    em.persist(e); 
    em.flush(); 

    return e; 
} 

实体表对对(类型,值)的唯一约束,我有如下的测试:

public void testCreateElement() throws DataAccessException { 
     // Start with empty Element table 

     Element e = new Element(); 
     e.setType(myType.OTHER); 
     e.setValue("1"); 
     dao.createElement(e); 

     e = new Element(); 
     e.setType(MyType.OTHER); 
     e.setValue("1"); 
     try{ 
       // this should violate unique constraint of database. 
       dao.createElement(e); 
     } catch (Exception ex) { 
      System.out.println(ex); 
     } 

     e.setValue("2"); 
     try{ 
      // I expect this to work as there is no element with these values. 
      dao.createElement(e); 
     } catch (Exception ex) { 
      System.out.println(ex); 
     } 
    } 

如我所料,因为我知道,我是我的第一个抓住了错误发生米违反约束,第二的try/catch应该不会引发错误就我而言,但它确实,我得到了这一点:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.mypackage.Element 

如此看来调用persist()的“电子“,即使它没有持续下去导致hibernate认为它是一个分离的实体。

这很烦人,因为这些函数正在被处理ConstraintViolation异常的JSF前端使用,但是故意保留该对象,以便用户可以更改其中一个字段并再次尝试,并且它们会得到分离的实体错误。

这种行为是休眠的错误,因为我不认为它应该被真正做这做?有没有解决的办法在DAO水平,使一直存在夺得;吨对待我的对象分开,如果它不是真正坚持?

问候,

格伦X

+0

只是为了笑容,如果你创建一个新的元素和您呼叫的最后的createElement之前设置正确的价值观发生了什么? – 2012-02-24 16:43:16

+0

它很好。 – Link19 2012-02-24 16:43:56

+0

这有帮助吗?如果没有,这可能会工作... e.setValue(1); e = dao.createElement(e); (< - 将失败),但然后e.setValue(2); edao.createElement(E); (< - 将有希望)。 – 2012-02-24 16:52:38

回答

3

由Hibernate抛出的异常是不可恢复的。在发生这种异常时,唯一应该做的事情是回滚事务并关闭会话。会议(及其实体)在这种例外之后的状态是不稳定的。

如果你想保持元素的副本不变,使用merge()而非persist(),或者坚持之前克隆的元素。

注意,例外是意料之中的,因为当休眠持续并刷新实体,它开始通过产生一个ID和分配ID的实体,然后插入一行,这会导致异常。所以,在例外之后,实体会分配一个ID,因此被Hibernate视为一个分离的实体。你可以尝试重置ID为空,看看它是否有效,但我宁愿先克隆实体或使用合并。