HibernateHibernate, al igual que la vida, está lleno de sopresas. Hoy vamos a compartir una de estas sorpresas: ¿se dieron cuenta que Hibernate tiene dos métodos para cargar una entidad persistente de la base de datos? Estos dos métodos son get(Class, Serializable) y load(Class, Serializable), pertenecientes a la clase Session y sus variantes.

Curioso, ambos métodos tienen la misma firma. Más curioso, la descripción del API de ambos métodos empieza igual: 

Retorna la instancia persistente de la clase dada con el identificador dado.

La mayoría de los desarrolladores los usan de forma indistinta. Y es un error, ya que cuando no se encuentra la entidad, el método get() devolverá null mientras que el método load() lanzará una excepción de Hibernate. Como bien lo explica el API del método load()

Retorna la instancia persistente de la clase dada con el identificador dado, asumiendo que la instancia existe. No se debe usar este método para determinar si una instancia existe (en cambio, usar get()). Sólo usar este método para recuperar una instancia que se asume existe, en donde la no existencia sería un error real.

La verdad es que la diferencia es otra: el método get() retorna una instancia, mientras que el método load() retorna un proxy. ¿No me creen? Prueben ejecutar el siguiente código: 

 
Session session = factory.getCurrentSession();
Foo foo = (Foo) session.get(Foo.class, 1);
 
// Verificamos la clase del objeto
assertSame(foo.getClass(), Foo.class);

La prueba pasará con éxito, verificando que la clase de la variable foo es realmente de la clase Foo. Ahora, en otra sesión, prueben lo siguiente: 

 
Session session = factory.getCurrentSession();
Foo foo = (Foo) session.load(Foo.class, 1);
 
// Verificamos la clase del objeto
assertNotSame(foo.getClass(), Foo.class); 

Esta prueba también pasará, comprobando que la clase de la variable foo no es Foo. Si miran la variable foo con un debugger, verán que es una instancia proxy y que sus campos no están inicializados! Noten que en ambos casos pueden castear esta instancia a Foo. Al invocar los getter también obtendrán los valores esperados.

Entonces, ¿para qué invocar al método load()?. Porque como es un proxy, no llegará hasta la base de datos hasta que se invoque algún método.

Más aún, estas características también están disponible en el EntityManager de JPA, a través de los métodos find() y getReference().

Ambos comportamientos se modifican con el mecanismo de caché de Hibernate. Prueben lo siguiente: 

 
// Cargar la referencia
session.load(Foo.class, 1);
 
Foo foo = (Foo) session.get(Foo.class, 1);

De acuerdo a lo dicho anteriormente, la clase de la variable foo debería ser un objeto Foo. ¡Error! Como invocamos previamente al método load(), el método get() buscará en el caché de la Session (el caché de primer nivel) y retornará un proxy.

Este comportamiento es simétrico, lo vemos con la siguiente prueba:

 
// Obtener el objeto
session.get(Foo.class, 1);
 
// Carga la referencia, pero la busca en el caché y encuentra la entidad real 
// que se obtuvo en la linea anterior.
Foo foo = (Foo) session.load(Foo.class, 1);
 
// Verificar la clase del objeto
assertSame(foo.getClass(), Foo.class);

Conclusión: Hibernate hace un excelente trabajo en simplificar el mapeo de objetos a bases de datos relacionados. Y sin embargo, no es un framework simple: debemos tener en cuenta estos cambios de comportamiento, entendiendo el funcionamiento del framework. 

Traducido de Hibernate hard facts 4, por Nicolas Frankel.

    Deja tus comentarios

    Post comment as a guest

    0

    Seguinos en Facebook.

    Publicá tus artículos.

    Publicar Convertite en redactor para Dos Ideas y compartí tus conocimientos a una comunidad que sigue creciendo!
    Quiero publicar

    Los Comentarios.

    invitado
    hasta ahora no sabia que era el cinismo pero ahora que lo se me he dado cuenta porque he tenido tant...
    Dai
    Es broma?
    busquen el significado de cinismo.
    esta el antiguo significado y el moderno,
    el moderno...
    Yan
    Hola:
    Unas duda, Drools ¿tiene una interfaz gráfica para poder generar y editar reglas? o todo se t...
    Maxi
    Gracias por la info, esta bien explicado y funciono como solución a mi problema que tenia con el mét...
    jonybuzz
    Cierto. Y más desafiante: Qué pasa si dejamos ir algo que sí funciona? Algo que sentimos que puede m...

    Inspiración.

    "Si tú tienes una manzana y yo tengo una manzana e intercambiamos las manzanas, entonces tanto tú como yo seguiremos teniendo una manzana cada uno. Pero si tú tienes una idea y yo tengo una idea, e intercambiamos las ideas, entonces ambos tendremos dos ideas"

    Bernard Shaw