2011-11-08 12 views
9

Sto cercando di capire qual è la differenza in oggetto restituito e comportamento di Hibernate 3.6 session.get() e session.load().Hibernate 3.6 - session.get() vs session.load()

Dal javadoc:

get():

Ritorna l'istanza persistente data classe di entità con la dato identificativo, o null se non esiste un'istanza persistente. (Se l'istanza è già associato con la sessione, tornare che esempio Questo metodo non restituisce un'istanza non inizializzata..)

load():

Ritorna l'istanza persistente data classe di entità con l'identificatore dato , supponendo che l'istanza esista. Questo metodo potrebbe restituire un'istanza con proxy che è inizializzata su richiesta, quando si accede a un metodo non identifier .

Ho tre domande:

  1. Javadoc non dice quando load() potrebbe restituire un proxy - non v'è alcun modo di sapere in anticipo?

  2. Quando load() restituisce un proxy - ciò significa che load() non ha accesso al database, sono corretto? Allora cosa succede se ho fornito load() con un identificatore che non esiste nel database? Ora avrò nella sessione un proxy con un ID non valido (senza ottenere un'eccezione). Ora voglio lasciare che un'altra istanza persistente punti a quel proxy: funzionerà? Per questo scenario non ho bisogno di inizializzare il proxy, ho solo bisogno del suo id (che ho anche se non è valido poiché non è nel database). Quindi suppongo che sto chiedendo se la mia descrizione è corretta, e ho sempre bisogno di controllare dopo load() l'oggetto restituito con isInitialized() per assicurarsi che rappresenti un'entità valida (o almeno un proxy valido), cioè con un valido ID.

  3. Inoltre, cosa succede se load() restituisce un proxy, quindi il proxy è l'istanza che è già associata alla sessione. Quindi, in base alla descrizione di get(): "Se l'istanza è già associata alla sessione, restituire tale istanza." - get() restituisce il proxy? Poiché in base alla descrizione di get(): "Questo metodo non restituisce mai un'istanza non inizializzata."

Grazie!

UPDATE

sono le seguenti corretta?

(A) Penso che sia load() e get() proverà prima a controllare la cache di sessione prima di andare al DB - quindi non sarebbe corretto dire che qualcuno di loro colpisce sempre il DB, o restituisce sempre un proxy.

(B) Un proxy inizializzato non è lo stesso che l'istanza originale, come potete leggere qui: http://blog.xebia.com/2008/03/08/advanced-hibernate-proxy-pitfalls/

risposta

17

(1), (3):

Sì. Hai ragione. Entrambi gli load() e get() controllano innanzitutto se c'è un'istanza con lo stesso PK persistente nella sessione.

Se sì, restituisce l'istanza dalla sessione. (Può essere il proxy o l'istanza della classe entità effettiva)

Se no, load() creerà e restituirà un proxy mentre get() colpirà DB e restituirà l'istanza della classe entità effettiva.

L'oggetto restituito da entrambi i metodi verrà associato e mantenuto nella sessione in seguito.

Quindi, sia il proxy di ritorno get() o load() o la classe di entità effettiva dipende dal fatto che si usi get() o load() per ottenere l'istanza dello stesso PK nella sessione corrente per la prima volta.

È possibile prova di questo comportamento eseguendo il seguente test:

Session session = HibernateUtil.getSessionFactory().openSession(); 

Item loadItem= (Item) session.load(Item.class, 1); 
System.out.println(loadItem.getClass().getName()); 

Item getItem = (Item) session.get(Item .class, 1); 
System.out.println(getItem .getClass().getName()); 

Se si tratta di un proxy, il nome della classe stampata non sarà lo stesso del nome effettivo classe di entità. Basta modificare l'ordine di esecuzione di load() e get() per vedere l'effetto.

(2):

Se il carico() restituisce un proxy, non sarà accedere al DB durante load() .La proxy accede solo il DB se le loro proprietà mappate oltre al PK sono accessibili e non ci sono casi con lo stesso valore PK è associato alla sessione.

Dopo che il proxy accede al DB, l'istanza con lo stesso PK del proxy sarà associata a quella sessione. Così quando si ottiene nuovamente un'altra proprietà dal proxy o si utilizza get() per ottenere l'istanza per lo stesso PK, il DB non sarà accessibile poiché i valori possono essere trovati dalla sessione.

Ad esempio:

/**Session starts***/ 
Item item = (Item) session.load(Item.class, new Long(1)); 
item.getId(); //Will not access DB as only the identifier property is access 
item.getDescription(); // access the DB and initialize the proxy . After that , the item proxy is said to be initialized 
item.getPrice(); //will not access DB as the item with the PK 1 can be get from the session 
Item item2 = session.get(Item.class, new Long(1)) //will not access DB as the item with the PK 1 can be get from the session 

Se load() un'istanza con l'ID non valido e quindi accedere alla proprietà o chiamare un metodo (come isInitialized()) su questo proxy, saranno gettati ObjectNotFoundException. Quindi, se puoi catturare ObjectNotFoundException, significa che un proxy è caricato con un ID non valido.

Se si desidera garantire che l'ID sia valido durante il runtime, è necessario utilizzare get() e verificare se l'istanza restituita è nullo. load() è utile quando si imposta il vincolo di chiave esterna. Vedi this

+0

1.Ma se avessi già un'istanza inizializzata (per questo ID) sulla sessione, non restituirebbe quell'istanza e non un proxy? Inoltre, javadoc dice: "Questo metodo potrebbe restituire un'istanza con proxy" - non dice "questo metodo sarà sempre". 2. È una sorta di difetto di progettazione - poiché in base a ciò che dici quando ho un proxy e voglio assicurarmi che rappresenti un ID effettivo in DB (e voglio sempre renderlo sicuro - anche se utilizzo solo il proxy per puntare ad altre istanze ad esso) - quindi non posso sapere che l'ID che ho usato è valido fino a quando non lo inizializzo, ma in questo caso, perché usare un proxy? – rapt

+0

3. Intendi un 'get()' dopo 'load()' restituirà un proxy inizializzato, o solo un'istanza inizializzata? Dal momento che se è il più tardi, ora abbiamo nella sessione due oggetti che contengono lo stesso ID (il proxy e l'istanza). A proposito, so che è possibile avere due proxy che rappresentano lo stesso ID DB, come potete leggere qui: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/ sotto il testo " In secondo luogo, è possibile rompere il proxy ". - Vedi di più in UPDATE nella mia domanda originale. – rapt

+0

Sì. Hai ragione. Le tue domande mi aiutano a chiarire qualche malinteso su 'get()' e 'load()'. Guarda il mio aggiornamento per favore –