Quando si a che fare con delle entity (padre) che hanno delle collection di altre entity (figli), Hibernate offre la possibilità di “tirare su” dal db la collection dei figli subito, nel momento in cui si accede al padre, o in un secondo momento, quando si cerca di accedere direttamente ai figli.
L’attributo che indica QUANDO prendere la collection dal db è lazy=”true|false”. Con true,detto anche comportamento lazy, l’oggetto figlio sarà preso dal db solo nel momento in cui viene invocato. Questo fa si che le query siano molto veloci, si prendono dal db solo i padri, però, se la lettura dei figli avviene fuori dal contesto di hibernate (come ad esempio un EJB), potremmo avere che la sessione è chiusa e quindi verrà sollevata una exception.
Con lazy = “false”, detto anche comportamento eager, non avremo problemi di sessione chiusa ma le prestazioni potrebbero decadere in quanto con una singola query si potrebbe tirare su tutto il DB.
Per indicare COME i figli devono essere letti dal db si l’attributo fetch = “select|subselect|join|batch”.
select: una seconda select è usata per leggere la collection, quindi Hibernate eseguirà una select per il padre e una select per i figli.
Se, per esempio, abbiamo 10 entity padre (A) e ciascuna padre ha al suo interno una collection di figli (B) di grandezza qualsiasi, verranno eseguite le seguenti select:
select A –> eseguita 1 volta, ci darà tutti i padri che ci interessano
select B where A.Id = ? —-> eseguita altre 10 volte
avremo quindi in totale 11 select eseguite. Questa opzione è quella di default.
join: verrà eseguita un’unica select, mettendo in JOIN il padre con tutti i suoi figli.
batch-size=N: questo è un po contorto, esso indica non quanti elementi della collection devono essere letti ma indica quante collection devono essere lette. Riconsiderando l’esempio precendente, se batch-size = 5 leggeremo al massimo 5 collection di figli per volta
select A —> 1 volta
select B where A.id in ( ?, ?, ?, ?, ? ) –> eseguito 10/5= 2 volte
le select totali questa volta sono 3, al posto delle 11 select richieste normalmente, un bel risparmio di tempo.
subselect: hibernate utilizzerà le subquery. In questo caso le select generate sono
select A—> 1 volta
select B where A.id in ( select A ) –> 1 volta
quindi in questo caso avremo 2 select in tutto.
Ogni opzione ha i suoi pro e i suoi contro, molto dipende dal tipo di DB usato e dalla complessità dello schema.