6

Hi I have a simple DAO with the below function.

    public element createElement(Element e){

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

    return e;
}

The Entity table has a unique constraint on the pair (type,value) and I have a test below:

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

My first caught error happens as I expect since I know that I'm violating the constraint, the second try/catch shouldn't throw an error as far as i'm concerned, but it does, what I get its this:

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

So it seems calling persist() on "e" even though it wasn't persisted has caused hibernate to think it's a detached entity.

This is annoying because these functions are getting used by a JSF front end that is dealing with the ConstraintViolation exception, but deliberately holding on to the object so that the user can change one of the fields and try again, and they get the detached entity error.

Is this behaviour a hibernate bug because I don't think it should be doing this really? Is there a way around this at the DAO level so that persist won;t treat my object as detached if it's not actually persisted?

Regards,

Glen x

4

1 に答える 1

3

Hibernateによってスローされた例外は回復できません。このような例外が発生したときに実行する必要があるのは、トランザクションをロールバックしてセッションを閉じることだけです。このような例外の後のセッション(およびそのエンティティ)の状態は不安定です。

要素のコピーを変更せずに保持する場合は、要素を永続化する前に、merge()ではなくを使用するかpersist()、要素のクローンを作成します。

Hibernateがエンティティを永続化してフラッシュするとき、IDを生成してエンティティにIDを割り当てることから始め、次に行を挿入して例外を発生させるため、例外が予想されることに注意してください。したがって、例外の後、エンティティにはIDが割り当てられているため、Hibernateによって切り離されたエンティティと見なされます。IDをnullにリセットして、それが機能するかどうかを確認することもできますが、マージの前にエンティティのクローンを作成するか、マージを使用することをお勧めします。

于 2012-02-24T17:15:10.397 に答える