2009-12-28 10 views
6

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?

  1. ho fatto qualcosa di sbagliato
  2. Qualcuno verifica lo stesso problema?
  3. 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)

+0

Il comportamento del recupero dipende dall'API utilizzata per eseguire query sugli oggetti. Stai usando l'API HQL o Criteria? – skaffman

+0

Né, un semplice session.load (Foo.class, id) –

risposta

4

Ho riscontrato lo stesso problema e mi sono ritrovato a contrassegnare tutte le relazioni molti-a-uno che verranno memorizzate nella cache come fetch="select". Nel momento in cui viene creata la query, Hibernate non può sapere se l'istanza richiesta di Bar si trova nella cache di secondo livello o meno (assumendo che Foo non sia nella cache).

+0

Ma non è strano che non sia documentato, nemmeno nei libri commerciali ufficiali?Anche nei forum o qui in SO non ho trovato menzioni di questo problema ... Sono d'accordo. –

+0

Ma per capire cosa fa esattamente l'ibernazione, spesso devo mettere su sql logging e dare un'occhiata a ciò che sta realmente accadendo. – bertolami

Problemi correlati