Domanda

Ciao ho un semplice dao con la funzione seguente.

    public element createElement(Element e){

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

    return e;
}

La tabella delle entità ha un vincolo unico sulla coppia (tipo, valore) e ho un test di seguito:

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

Il mio primo errore catturato avviene come mi aspetto dal momento che so che sto violando il vincolo, il secondo tentativo/cattura non dovrebbe lanciare un errore per quanto mi riguarda, ma lo fa, quello che ottengo è questo:

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

Quindi sembra chiamare persistere () su "e" anche se non è stato persistito ha fatto sì che Hibernate pensasse che sia un'entità distaccata.

Questo è fastidioso perché queste funzioni vengono utilizzate da un front -end JSF che sta affrontando l'eccezione di vincolo, ma trattenendo deliberatamente l'oggetto in modo che l'utente possa cambiare uno dei campi e riprovare e provare l'errore di entità distaccata .

Questo comportamento è un bug in letargo perché non penso che dovrebbe farlo davvero? C'è un modo per aggirare questo a livello di DAO in modo che persiste non trattare il mio oggetto come distaccato se non è effettivamente persistito?

Saluti,

Glen x

È stato utile?

Soluzione

Un'eccezione lanciata da Hibernate non è recuperabile. L'unica cosa che dovresti mai fare quando si verifica tale eccezione è il rollback e chiudere la sessione. Lo stato della sessione (e delle sue entità) dopo tale eccezione è instabile.

Se vuoi conservare una copia dell'elemento intatta, usa merge() piuttosto che persist(), o clonare l'elemento prima di persistere.

Si noti che è prevista l'eccezione, poiché quando Hibernate persiste e scarica l'entità, inizia generando un ID e assegnando l'ID all'entità, quindi inserisce la riga, il che provoca l'eccezione. Quindi, dopo l'eccezione, l'entità ha un ID assegnato ed è quindi considerata un'entità distaccata da Hibernate. Potresti provare a ripristinare l'ID su NULL e vedere se funziona, ma preferirei clonare l'entità prima o uso unione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top