2010-09-13 10 views
10

Ho caricato un'entità nella mia transazione e ho modificato una proprietà di tale entità. La transazione non è ancora impegnata. Ora vorrei ottenere il valore originale della proprietà modificata.Forza la query di ibernazione per accedere al database

Ho provato con una query HQL come select p.property from Person p where p.id = 1 con l'ID dell'entità caricata nella transazione.

Ho impostato query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE); prima di eseguire la query. Ma nessun successo. Hibernate restituisce il valore impostato nella transazione corrente, non quello dal database.

C'è qualche modo per aggirare questo?

+0

Non si finisce con il problema in cui Hibernate si lamenta della stessa entità che si trova nella sessione due volte? Sembra che potresti voler rivisitare l'implementazione. –

risposta

11

Ho caricato un'entità nella mia transazione e ho modificato una proprietà di tale entità. La transazione non è ancora impegnata. Ora vorrei ottenere il valore originale della proprietà modificata.

In breve: traccia il valore precedente da solo.

Ho provato con una query HQL come selezionare p.property da Person p dove p.id = 1 con l'ID dell'entità caricata nella transazione.

Hibernate carichi una versione unica di un'entità nella sessione (la prima cache livello) per un dato identificatore del database. Questo non funzionerà.

Ho impostato query.setHint ("org.hibernate.cacheMode", CacheMode.IGNORE); prima di eseguire la query.

Questo suggerimento è usata per influenzare la cache interrogazione (che si basano sul secondo livello-cache), questo non influenzerà il vostro "problema" corrente.

C'è qualche modo per aggirare questo?

In entrambi i

  • uso session.refresh() per forzare un ricaricamento della vostra entità (e ti perdere le modifiche)
  • memorizzare il valore precedente, come inizialmente indicato.
  • richiama un servizio che esegue una query in un'altra transazione.
2

Questo può aiutare:

Se si vuole forzare la cache delle query per aggiornare una delle sue regioni (ignorare risultati memorizzati nella cache che trova lì) è possibile utilizzare org.hibernate.Query .setCacheMode (CacheMode.REFRESH). In combinazione con la regione che è stata definita per la query specificata , Hibernate imporrà selettivamente i risultati nella cache in quella particolare regione da aggiornare. Questo è particolarmente utile nei casi in cui dati di riferimento possono essere stati aggiornati tramite un processo separato ed è di gran lunga più efficiente alternativa alla rinfusa sgombero della regione tramite org.hibernate.SessionFactory.evictQueries().

(da http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html, sezione 20.4.2).

Tuttavia, è destinato a essere utilizzato quando altri processi aggiornano il DB e deve essere utilizzato con attenzione. Il tuo caso è diverso. Poiché questo metodo si verifica al di fuori di qualsiasi transazione, è necessario assicurarsi che non sia in conflitto con il progetto. Forse puoi refactoring il tuo flusso di chiamata per evitare tale comportamento e recuperare il campo da un'altra fonte o prima che la modifica nella cache abbia luogo ...

+0

Rivedere la mia risposta Vedo che non risolve completamente il problema. Anche se disabiliti completamente la cache di secondo livello, i tuoi dati di entità potrebbero arrivare per la cache di primo livello (sessione). Per questo, è necessario aggiornare o sfrattare l'oggetto ... ma è necessario reinserire i campi che si desidera salvare nel commit della transazione. – Sebastian

1

L'unico modo per farlo sarebbe quello di eseguire la query al di fuori del transazione corrente.

7

La StatelessSession ha funzionato per me.

StatelessSession statelessSession = sessionFactory.openStatelessSession(); 
try { 
    return statelessSession.get(Ticket.class, ticketKey, LockMode.READ) 
} finally { 
    statelessSession.close() 
} 
Problemi correlati