A cosa serve session.flush () in Hibernate


110

Quando stiamo aggiornando un record, possiamo usarlo session.flush()con Hibernate. A cosa serve flush()?

Risposte:


138

Lo svuotamento della sessione forza Hibernate a sincronizzare lo stato in memoria di Sessioncon il database (cioè a scrivere le modifiche nel database). Per impostazione predefinita, Hibernate scaricherà automaticamente le modifiche:

  • prima di alcune esecuzioni di query
  • quando viene eseguito il commit di una transazione

Consentire di svuotare esplicitamente il Sessiondà un controllo più preciso che può essere richiesto in alcune circostanze (per ottenere un ID assegnato, per controllare la dimensione della Sessione, ...).


8
Si noti che questa risposta descrive il comportamento di ibernazione PREDEFINITO: il comportamento di scarico può essere modificato tramite l'impostazione della modalità di lavaggio. I dettagli sono in docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/… (versione 3.5).
SteveT

1
Ho trovato il documento in cui si dice esattamente quello che stai dicendo ma ho dubbi sul fatto che quale sarà la priorità significa supporre 1) Ho una classe in cui sto salvando l'oggetto usando il codice id = session.save(obj);e la transazione viene eseguita nella riga successiva ma obj non viene salvato a DB, perché? 2) Ho salvato obj usando session.save(obj);con commit e durante il ritorno ho usato return obj.getprimaryID();In questo caso obj viene salvato su DB. Allora perché questo comportamento sta accadendo?
Amogh

74

Come giustamente detto nelle risposte precedenti, chiamando flush()forziamo l'ibernazione per eseguire i comandi SQL su Database. Ma comprendi che i cambiamenti non sono ancora "impegnati". Quindi, dopo aver eseguito il flush e prima di eseguire il commit, se accedi direttamente al DB (diciamo dal prompt SQL) e controlli le righe modificate, NON vedrai le modifiche.

Equivale all'apertura di 2 sessioni di comandi SQL. E le modifiche apportate in 1 sessione non sono visibili agli altri finché non vengono eseguite.


12
Bene, le modifiche possono essere leggermente visibili. Ad esempio, una riga di cui non è stato eseguito il commit può creare un blocco sulla riga inserita ma non salvata e ritardare l'inserimento della stessa riga da parte di un'altra sessione fino a quando non viene eseguito il commit o il rollback della transazione. Quindi non è completamente invisibile.
rghome

2
Ho navigato in tutto il web e questa è la risposta che finalmente me l'ha fatta capire. Grazie.
Siddhartha

a che serve mettere .flush () in un ciclo for, se commit () esegue un flush alla fine?
Eildosa

@Kaushik Lele Qual è il punto di flush () se i dati non sono visibili dopo il flush? Puoi elaborare alcuni dei casi d'uso più raffinati in cui questo è utile?
java_geek

28

So solo che quando chiamiamo le session.flush()nostre istruzioni vengono eseguite nel database ma non impegnate.

Supponiamo di non chiamare il flush()metodo sull'oggetto sessione e se chiamiamo il metodo commit, internamente eseguirà le istruzioni sul database e quindi eseguirà il commit.

commit=flush+commit (in caso di funzionalità)

Quindi, concludo che quando chiamiamo il metodo flush () sull'oggetto Session, allora non ottiene il commit ma colpisce il database ed esegue la query e ottiene anche il rollback.

Per eseguire il commit usiamo commit () sull'oggetto Transaction.


Puoi fornire alcuni dettagli su che cosa è necessario per lo scarico?
java_geek

14

Lo svuotamento della sessione ottiene i dati attualmente nella sessione sincronizzati con ciò che è nel database.

Maggiori informazioni sul sito Web di Hibernate:

flush()è utile, perché non ci sono assolutamente garanzie su quando la sessione esegue le chiamate JDBC, solo l'ordine in cui vengono eseguite, tranne che si usa flush().


Potete fornire uno scenario in cui l'utente dovrebbe preoccuparsi della sequenza? L'uso di ibernazione serve a rendere trasparenti all'utente le cose relative al DB. Quando eseguiamo il "commit", lo scaricamento avviene automaticamente. Qual è lo scenario in cui eseguirai il flush ma non ti impegnerai?
Kaushik Lele

1
@KaushikLele è possibile fare riferimento a questa domanda stackoverflow.com/questions/37382872/...
GMsoF

10

È possibile utilizzare flushper forzare la realizzazione e il rilevamento dei vincoli di convalida in un luogo noto anziché quando viene eseguito il commit della transazione. Può essere che commitvenga chiamato implicitamente da una logica del framework, tramite la logica dichiarativa, il contenitore o un modello. In questo caso, qualsiasi eccezione generata potrebbe essere difficile da intercettare e gestire (potrebbe essere troppo alta nel codice).

Ad esempio, se save()utilizzi un nuovo oggetto EmailAddress, che ha un vincolo univoco sull'indirizzo, non riceverai un errore finché non effettui il commit.

La chiamata flush()forza l'inserimento della riga, generando un'eccezione se è presente un duplicato.

Tuttavia, sarà necessario ripristinare la sessione dopo l'eccezione.


4

Vorrei solo associare tutte le risposte fornite sopra e correlare anche il metodo Flush () con Session.save () in modo da dare più importanza

Hibernate save () può essere utilizzato per salvare l'entità nel database. Possiamo invocare questo metodo al di fuori di una transazione, ecco perché non mi piace questo metodo per salvare i dati. Se lo usiamo senza transazione e abbiamo una cascata tra le entità, viene salvata solo l'entità primaria a meno che non svuotiamo la sessione.

flush (): forza lo scaricamento della sessione. Viene utilizzato per sincronizzare i dati della sessione con il database.

Quando chiamate session.flush (), le istruzioni vengono eseguite nel database ma non verrà eseguito il commit. Se non chiami session.flush () e se chiami session.commit (), il metodo commit () internamente esegue l'istruzione e si impegna.

Quindi commit () = flush + commit. Quindi session.flush () esegue solo le istruzioni nel database (ma non esegue il commit) e le istruzioni NON sono più IN MEMORIA. Forza solo lo scarico della sessione.

Pochi punti importanti:

Dobbiamo evitare di salvare al di fuori del confine della transazione, altrimenti le entità mappate non verranno salvate causando incoerenze nei dati. È molto normale dimenticare di svuotare la sessione perché non genera eccezioni o avvisi. Per impostazione predefinita, Hibernate scaricherà automaticamente le modifiche per te: prima che alcune esecuzioni di query quando una transazione venga salvata Consentire di svuotare esplicitamente la Sessione fornisce un controllo più preciso che potrebbe essere richiesto in alcune circostanze (per ottenere un ID assegnato, per controllare la dimensione della Sessione )


3

Il flush() metodo fa in modo che Hibernate scarichi la sessione. È possibile configurare Hibernate per utilizzare la modalità di svuotamento per la sessione utilizzando il setFlushMode()metodo. Per ottenere la modalità flush per la sessione corrente, puoi usare getFlushMode()method. Per verificare se la sessione è sporca, puoi usare il isDirty()metodo. Per impostazione predefinita, Hibernate gestisce lo svuotamento delle sessioni.

Come indicato nella documentazione:

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html

risciacquo

Lo svuotamento è il processo di sincronizzazione dello stato del contesto di persistenza con il database sottostante. E EntityManagerHibernate Sessionespongono una serie di metodi, attraverso i quali lo sviluppatore dell'applicazione può modificare lo stato persistente di un'entità.

Il contesto di persistenza funge da cache write-behind transazionale, accodando qualsiasi modifica dello stato dell'entità. Come qualsiasi cache write-behind, le modifiche vengono prima applicate in memoria e sincronizzate con il database durante il tempo di scaricamento. L'operazione di incasso prende ogni entità cambiamento di stato e lo traduce in un INSERT, UPDATEo di DELETEdichiarazione.

La strategia di svuotamento è data dal flushMode della sessione Hibernate attualmente in esecuzione. Sebbene JPA definisca solo due strategie di lavaggio ( AUTOe COMMIT), Hibernate ha uno spettro molto più ampio di tipi di lavaggio:

  • ALWAYS: Svuota la sessione prima di ogni query;
  • AUTO: Questa è la modalità predefinita e scarica la sessione solo se necessario;
  • COMMIT: La Sessione cerca di ritardare lo scaricamento fino a quando non viene confermata la Transazione corrente, sebbene potrebbe anche scaricarsi prematuramente;
  • MANUAL: Lo svuotamento della sessione è delegato all'applicazione, che deve chiamare Session.flush()esplicitamente per applicare le modifiche al contesto di persistenza.

Per impostazione predefinita, Hibernate utilizza la AUTOmodalità flush che attiva un flush nelle seguenti circostanze:

  • prima di effettuare una transazione;
  • prima di eseguire una query JPQL / HQL che si sovrappone alle azioni dell'entità in coda;
  • prima di eseguire qualsiasi query SQL nativa senza sincronizzazione registrata.

1

La chiamata EntityManager#flushha effetti collaterali . È convenientemente utilizzato per i tipi di entità con valori ID generati (valori di sequenza): tale ID è disponibile solo al momento della sincronizzazione con il livello di persistenza sottostante. Se questo ID è richiesto prima del termine della transazione corrente (ad esempio per scopi di registrazione), è necessario svuotare la sessione.


0

Con questo metodo si evoca il processo di lavaggio. Questo processo sincronizza lo stato del database con lo stato della sessione rilevando i cambiamenti di stato ed eseguendo le rispettive istruzioni SQL.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.