JPA EntityManager persist () заставляет объект казаться отсоединенным, даже если была выдана ошибка - PullRequest
6 голосов
/ 24 февраля 2012

Привет, у меня есть простой DAO с функцией ниже.

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

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

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

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

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

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

С уважением,

Глен х

1 Ответ

3 голосов
/ 24 февраля 2012

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...