2014-04-22 12 views
6

Vorrei sapere quale approccio adottare per impedire a Hibernate 4.3.4 (con Spring e Hibernate Vaidator) di svuotare le entità sporche. Nel mio codice, utilizzo un'implementazione manuale di Hibernate Validator (un metodo .validate() all'interno dell'istanza stessa), che viene chiamato appena prima di salvare un'entità. Il metodo validate() restituisce un elenco di errori, se presenti, altrimenti viene chiamato un Session.update() per memorizzare l'entità, seguito da un commit della transazione.Impedire la sessione di sospensione dallo svuotamento/archiviazione di entità dirty non valide

Questo funziona, ma quando l'istanza stessa viene manipolata (i parametri di registrazione/richiesta sono impostati nell'entità) l'entità e la sessione di Hibernate corrispondente sono contrassegnate come "dirty" e l'entità viene archiviata con la successiva Session.flush().

Nel mio caso, vorrei avere un controllo esplicito sulle entità che possono essere memorizzate e impedire la memorizzazione di qualsiasi entità sporca, come potrei ottenere questo?

EDIT:

so di poter regolare manualmente questo sfrattando un'entità (o compensazione e ripristina un'entità tramite una fusione), ma questo non è il mio scopo. Piuttosto che dover regolare manualmente la persistenza, vorrei avere la situazione di offset che nessuna entità che non è stata salvata esplicitamente e di cui la transazione non è stata esplicitamente impegnata, non verrà memorizzata nel database (ad esempio tramite un intercettore?).

risposta

6

Se si modificano entità e si desidera esplicitamente che non vengano scaricate, è possibile scollegarle prima di modificarle. Le entità distaccate non saranno più gestite dal contesto di persistenza.

Hibernate API:

session.evict(myEntity)

JPA:

entityManager.detach(myEntity)

EDIT: Nel caso in cui si desidera staccare tutte le entità e gestire solo alcuni di essi, è possibile cancellare la prima il contesto di persistenza e poi unire le entrate che si desidera gestire do:

Hibernate API:

session.clear(); 
managedEntity = session.merge(detachedEntity); 

JPA:

entityManager.clear(); 
managedEntity = entityManager.merge(detachedEntity); 

EDIT 2 Tutte le modifiche alle entità gestite sono lavata sulla transazione commesso. Non sono a conoscenza di alcuna funzionalità di JPA o Hibernate che possa disattivare questo comportamento. Quindi, oltre a staccare alcune o tutte le entità, avete alcune altre scelte, ma nessuno è esattamente quello che stai cercando:

  • andare a prendere i soggetti al di fuori di una transazione, in modo che siano distaccato immediatamente. Questo sembra avvicinarsi di più a ciò che vuoi: nessun problema con le modifiche gestite, solo l'unione esplicita salverebbe un'entità e dovresti gestire meno con l'API di persistenza. Tuttavia, sarà comunque necessario aprire una sessione per unire le entità che si desidera salvare con le modifiche.

  • risultati di query di mappatura a DTO/POJO (che sono sempre scollegati) utilizzando l'operatore NEW nelle query. Questo approccio ha il vantaggio di separare il mapping di persistenza dall'applicazione. Tuttavia, l'introduzione di un gruppo di nuove classi potrebbe non valerne la pena, e il fatto di non eseguirle in modo coerente nell'intera applicazione aggiunge complessità concettuale.

  • lavoro all'interno di una transazione, ma il rollback anziché il commit. Non si sarebbe in grado di salvare nulla ed è un modo un po 'rozzo per impedire che le modifiche vengano sincronizzate con il DB. Sfortunatamente, è necessario eseguire il commit o il rollback di una transazione.

  • creazione di copie profonde delle entità per modificarle. Francamente, questo non ha molto senso per me, aggiungendolo solo per completezza.

EDIT 3 Anche se non specificato dalle specifiche dell'APP, sia Hibernate e EclipseLink permettono marcatura operazioni o insiemi di risultati da una singola query in sola lettura. Questo potrebbe essere utile per voi, come

Quando un oggetto persistente è di sola lettura, Hibernate non sporca-check semplici proprietà

Change rossore diventa un po 'più complicata quando si tratta di rapporti. Si prega di fare riferimento a this documentation for Hibernate o this one for Eclipselink.

+0

Ciao Kostja, questa è la soluzione "inversa", ma non quello a cui sto mirando. Quello che voglio è che la situazione sia viceversa, solo le entità esplicitamente salvate e impegnate possono essere svuotate - di default, senza distaccarle, se possibile. – Marius

+0

Certo, puoi modificare il contesto di persistenza in entrambi i modi. Si prega di consultare la modifica. – kostja

+0

Quasi lì, ma ancora non completamente ciò che sto cercando di ottenere. Non voglio davvero preoccuparmi delle entità sporche e regolare la persistenza nel modo in cui descrivi, ma piuttosto, per esempio tramite un intercettore, mai (automatico) svuotare quelle entità quando non sono esplicitamente salvate e la transazione non è stata esplicitamente impegnata per impostazione predefinita, senza reintrodurli nella sessione di ibernazione, né doverli sfrattare prima del lavaggio. – Marius

Problemi correlati