2012-02-24 2 views
6

Привет У меня есть простой DAO с функцией ниже.JPA EntityManager persist() вызывает отключение объекта, даже если ошибка была сброшена

public element createElement(Element e){ 

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

    return e; 
} 

таблица Entity имеет единственное ограничение на пары (тип, значение) и у меня есть тест ниже:

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

Моя первая поймала ошибка происходит, как я ожидаю, так как я знаю, что я м нарушив ограничение, то вторая попытка/улов не должен выдавать ошибку, насколько я могу судить, но это не то, что я получаю это его:

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

так кажется вызовом сохраняется() на " e ", хотя он не вызвало спящий режим, чтобы думать, что это отдельный объект.

Это раздражает, потому что эти функции используются интерфейсом JSF, который имеет дело с исключением ConstraintViolation, но намеренно удерживает объект, чтобы пользователь мог изменить одно из полей и повторить попытку, и они получают ошибка отдельного объекта.

Является ли это поведение ошибкой спящего режима, потому что я не думаю, что это должно быть так? Есть ли способ обойти это на уровне DAO, чтобы упорство не выиграло, я рассматриваю свой объект как отдельный, если он на самом деле не сохраняется?

Привет,

Глен х

+0

Как раз для усмешки, что произойдет, если вы создадите новый элемент и установите правильные значения перед последним элементом createElement, который вы вызываете? –

+0

Все идет хорошо. – Link19

+0

Это помогает? Если нет, это может сработать ... e.setValue (1); e = dao.createElement (e); (<- сбой), но затем e.setValue (2); edao.createElement (е); (<- будем работать, надеюсь). –

ответ

3

Исключение брошенной Hibernate не может быть восстановлен. Единственное, что вы должны делать, когда возникает такое исключение, - это откат транзакции и закрытие сеанса. Состояние сеанса (и его сущностей) после такого исключения неустойчиво.

Если вы хотите сохранить копию элемента нетронутым, используйте merge(), а не persist(), или клонируйте элемент перед его сохранением.

Обратите внимание, что ожидается исключение, поскольку, когда Hibernate сохраняется и удаляет объект, он начинается с генерирования идентификатора и назначения идентификатора сущности, а затем вставляет строку, которая вызывает исключение. Таким образом, после исключения объект имеет назначенный идентификатор и, таким образом, считается спящим объектом по Hibernate. Вы можете попробовать сбросить идентификатор до нуля и посмотреть, работает ли он, но я бы предпочел клонирование объекта до или с помощью слияния.

Смежные вопросы