Quando Hibernate scarica una sessione, come decide quali oggetti della sessione sono sporchi?

La mia comprensione di Hibernate è che quando gli oggetti vengono caricati dal DB vengono aggiunti alla Session. In vari punti, a seconda della configurazione, la sessione viene svuotata. A questo punto, gli oggetti modificati vengono scritti nel database.

In che modo Hibernate decide quali oggetti sono “sporchi” e devono essere scritti?

I proxy generati da Hibernate intercettano le assegnazioni ai campi e aggiungono l’object a una lista sporca nella Sessione?

O Hibernate guarda ogni object nella Session e lo confronta con lo stato originale degli oggetti?

O qualcosa di completamente diverso?

Hibernate fa / può usare la generazione bytecode (CGLIB) in modo che sappia che un campo è sporco non appena si chiama il setter (o addirittura si assegna al campo afaict).

Questo contrassegna immediatamente quel campo / object come sporco, ma non riduce il numero di oggetti che devono essere controllati sporchi durante lo scarico. Tutto ciò che fa è un impatto sull’implementazione di org.hibernate.engine.EntityEntry.requiresDirtyCheck() . Effettua ancora un confronto field-by-field per verificare la presenza di sporcizia.

Dico quanto sopra basato su una recente scia attraverso il codice sorgente (3.2.6GA), con qualsiasi credibilità che aggiunge. I punti di interesse sono:

  • SessionImpl.flush() triggers un evento onFlush() .
  • SessionImpl.list() chiama autoFlushIfRequired() che triggers un evento onAutoFlush() . (sui tavoli di interesse). Cioè, le query possono richiamare un flush. È interessante notare che nessun stream si verifica se non vi è alcuna transazione.
  • Entrambi questi eventi finiscono in AbstractFlushingEventListener.flushEverythingToExecutions() , che finisce (tra le altre posizioni interessanti) su flushEntities() .
  • Questo loop su ogni quadro nella sessione ( source.getPersistenceContext().getEntityEntries() ) chiama DefaultFlushEntityEventListener.onFlushEntity() .
  • Alla fine dirtyCheck() a dirtyCheck() . Questo metodo apporta alcune ottimizzazioni a flag dirty CGLIB, ma abbiamo ancora finito il looping su ogni quadro.

Hibernate acquisisce un’istantanea dello stato di ciascun object che viene caricato nella Session. A livello, ogni object nella Sessione viene confrontato con la relativa istantanea corrispondente per determinare quali sono sporchi. Le istruzioni SQL vengono emesse come richiesto e le istantanee vengono aggiornate per riflettere lo stato degli oggetti di sessione (ora puliti).

Dai un’occhiata a org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck Ogni elemento della sessione va a questo metodo per determinare se è sporco o meno confrontandolo con una versione non modificata (una dalla cache o una dal database).

Il meccanismo di controllo dello sporco predefinito di Hibernate attraverserà le quadro allegate correnti e abbinerà tutte le proprietà ai loro valori iniziali di tempo di caricamento.

Puoi visualizzare meglio questo processo nel seguente diagramma:

Controllo sporco automatico predefinito

Queste risposte sono incomplete (nella migliore delle ipotesi – non sono un esperto qui). Se nella tua sessione hai un’ quadro uomo Hib, non fai NIENTE ad esso, puoi ancora ricevere un aggiornamento quando chiami save () su di esso. quando? quando un’altra sessione aggiorna quell’object tra load () e save (). ecco il mio esempio di questo: hibernate imposta flag dirty (e aggiorna i problemi) anche se il client non ha cambiato valore