Ho verificarsi il seguente problema, apparentemente privi di documenti, e voglio capire seHibernate Oggetti cache di secondo livello che sono lazy = false, generano un recupero predefinito = join, è documentato ovunque?
- ho fatto qualcosa di sbagliato
- Qualcuno verifica lo stesso problema?
- Davvero non è documentato da nessuna parte? o mi sono perso qualcosa?
Il comportamento è questo Assumere il seguente mappatura
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar"/>
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
In primo luogo, come sfondo, Hibernate valore predefinito per l'fetch attributo su una relazione molti-a-uno dovrebbe essere "selezionare ", questo è almeno quello che è documentato (aggiungerò il link qui quando lo trovo)
Tuttavia, questo è apparentemente vero solo se la classe di riferimento è lazy =" true "!
così apparentemente la mappatura di cui sopra si traduce in questo (perché è pigro Bar = "false"):
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Ora, perché vorrei che essere un problema? invece di 2 seleziona, Hibernate caricherà il riferimento non pigro in una singola selezione con il suo "parent" (carica Foo con Bar in una singola selezione)
questo in realtà ha senso, poiché l'oggetto non è pigro, perché non caricare vero?
La risposta è questa: cosa succede se Bar si trova nella cache di secondo livello?
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
<cache usage="transactional" />
...
</class>
E la risposta è che non cambia nulla!
Apparentemente si potrebbe supporre Hibernate è abbastanza intelligente per capire che oggetti di questo tipo non dovrebbero essere caricati, ma dal momento che il default recuperare è stato cambiato da selezionare per unirsi, Hibernate non avere una scelta (non è possibile partecipare a una vero tavolo con la cache di 2 ° livello, ancora)
modo Hibernate fa quello che viene detto, e utilizza un join per recuperare un oggetto dal database in cui è già presente nella cache di 2 ° livello
la soluzione che ho trovato è di cambiare letteralmente il mapping per fetch = "select"
Ora quando la seconda selezione per Bar è in procinto di andare, Hibernate comprende che non dovrebbe andare al database e recuperarlo dalla cache. e solo 1 query verrà eseguita (dopo il riscaldamento)
Il comportamento del recupero dipende dall'API utilizzata per eseguire query sugli oggetti. Stai usando l'API HQL o Criteria? – skaffman
Né, un semplice session.load (Foo.class, id) –