Hibernate: Recuperación de objetos. Fetch y Lazy

Hibernate recupera la información de la base de datos de una forma peculiar.

Existen dos conceptos importantes que debemos controlar cuando se trabaja con Hibernate:

  • Cuándo decide Hibernate recuperar la información de la base de datos y cargarla en memoria.
  • De qué forma se trae la información de la base de datos, es decir, qué sentencias SQL utiliza para recuperar la información.


Cuando Hibernate accede a una entidad que se relaciona con otras mediante asociaciones ¿cómo recupera la información?

Criteria consulta = session.createCriteria(Empresa.class);
List empresas = consulta.list();

Recupera todas empresas, pero, ¿también recupera todos los empleados asociados a la empresa?

 

Modo Lazy

Hibernate, por defecto, maneja las asociaciones de la siguiente manera:

  • Recupera los objetos Empresa.
  • Sólo cuando de forma programática se accede a los objetos de la asociación, Hibernate recupera los objetos Empleado de la base de datos.

Este comportamiento viene configurado por un parámetro llamado lazy que por defecto está a false. Hibernate tiene un  comportamiento perezoso por defecto.

Define cuándo se recupera la información de la asociación.

Este modo se puede parametrizar mediante los siguientes valores:

  • true.
  • false.
  • extra.

 

Modo Fetch

 Define cómo se recupera la información de la base de datos.

El parámetro fetch configura este comportamiento. Toma dos valores:

  • select: valor por defecto.
  • join.
  • subjoin.

 

Ejemplo

 

Entidad Empresa:

...
<hibernate-mapping package="modelo">
<class name="Empresa" table="empresa" >
<id name="id" column="idEmpresa" type="long">
<generator class="increment"></generator>
</id>
...
<set name="empleados">
<key column="idEmpresa"></key>
<one-to-many class="Empleado"/>
</set>
</class>
</hibernate-mapping>

 

Entidad Empleado:

...
<hibernate-mapping package="modelo">
<class name="Empleado" table="empleado" >
<id name="id" column="idEmpleado" type="long">
<generator class="increment"></generator>
</id>
<property name="nombre" column="nombre" type="string" />
<property name="sueldo" column="sueldo" type="double" />
</class>
</hibernate-mapping>

Código Java:

 …

Criteria consulta = sesion.createCriteria(Empresa.class);
List lista = consulta.list();
...

Se lanza SÓLO una select para Empresa, es decir, Hibernate NO carga en memoria los objetos de tipo Empleado inicialmente.

SÓLO cuando Hibernate detecta que se va a acceder a la información de Empleados se generan las correspondientes select.

 

...
for (int i = 0; i < lista.size(); i++) {
Empresa e = (Empresa)lista.get(i);
Set<Empleado> empleados = e.getEmpleados();
Iterator<Empleado> it = empleados.iterator();
while (it.hasNext()) {
Empleado empleado = (Empleado) it.next();
}
}
...

Esto ocurre porque con la configuración que se ha definido inicialmente se está trabajando con:

  • ” fetch=”select”.
  • ” lazy=”true”.

Se pasa a modificar a continuación la configuración del problema para comprobar su comportamiento.

 

Entidad Empresa -Modificación 1-

...
<hibernate-mapping package="modelo">
<class name="Empresa" table="empresa" >
<id name="id" column="idEmpresa" type="long">
<generator class="increment"></generator>
</id>
...
<set name="empleados" fetch="select" lazy="false">
<key column="idEmpresa"></key>
<one-to-many/>
</set>
</class>
</hibernate-mapping>

 

Código -Modificación 1-

 ...
Criteria consulta = sesion.createCriteria(Empresa.class);
List lista = consulta.list();
...

Se lanza una select para Empresa y otras select para recuperar todos los empleados, es decir, en este caso SÍ se recupera la información del otro extremo de la asociación.

 

Entidad Empresa -Modificación 2-

...
<hibernate-mapping package="modelo">
<class name="Empresa" table="empresa" >
<id name="id" column="idEmpresa" type="long">
<generator class="increment"></generator>
</id>
...
<set name="empleados" fetch="join”>
<key column="idEmpresa"></key>
<one-to-many/>
</set>
</class>
</hibernate-mapping>

 

Código -Modificación 2-

 ...
Criteria consulta = sesion.createCriteria(Empresa.class);
List lista = consulta.list();
...

 

Se lanza SÓLO select para recuperar Empresas y empleados, es decir, en este caso se recupera la información del otro extremo de la asociación con una ÚNICA CONSULTA.

 

Comments are closed.