Cómo el proxy carga la propiedad perezosa en Hibernate / JPA

Bueno, mi duda es muy simple: para un mejor rendimiento, se recomienda usar una inicialización siempre perezosa en propiedades que no necesito usar (esto es obvio). Entonces, imagina la siguiente clase:

@Entity public class Person{ @Column private String name; @ManyToOne(fetch = FetchType.Lazy) @JoinColumn(name = "id_type") private TypePerson type; } 

En mi clase principal, llamo a la Persona con el atributo “tipo” no inicializado, como a continuación:

  public void init(){ //in this point "type" attribute is not initialized Person person = dao.find("Select * from Person where id = 12"); //proxys work here to get description of "type" attribute System.out.println(person.getType().getDescription()); } 

Entonces, obtengo un objeto Person simple de dataBase e imprimo en la consola el tipo de persona. En este momento, Proxy CGLIB funciona y hace su magia, y todo funciona bien.

Pero aquí voy mi pregunta:

1 – Cuando solicito el “getType ()”, la Hibernación (u otro mecanismo) realiza una consulta SQL detrás de escena. Me gusta: “SELECT * FROM TypePerson where id = 3”.

Si la respuesta es sí: este método para obtener el valor de una propiedad puede ser muy doloroso, porque creo que Hibernate va cada vez en la base de datos para obtener esta información detrás de la escena.

Si la respuesta es no: ¿Cómo sabe Proxy el valor de la propiedad si no se cargó desde dataBase?

Cuando usted llama

 person.getType().getDescription() 

Si la person hace referencia a un proxy de Hibernate que no se ha inicializado, entonces, sí, emitirá una consulta SQL para recuperar los valores de campo de la entidad de destino.

Este método para obtener el valor de una propiedad puede ser muy doloroso, porque creo que Hibernate va cada vez en la base de datos para obtener esta información entre bambalinas.

Sólo irá una vez por cada proxy. Cuando vaya por primera vez, establecerá un indicador en el proxy que indica que está inicializado y, por lo tanto, la entidad objective subyacente tiene el valor correcto. No es necesario volver a la base de datos si tiene todos sus valores cargados.

Esta no es exactamente la forma en que Hibernate crea sus proxies, pero es una buena lectura: Proxy Pattern .

  1. En realidad, va a la base de datos cuando se llama al método getDescription() en el proxy devuelto por person.getType() .
  2. Va a la base de datos solo si llama a un método en el proxy, es decir, cuando realmente desea cargar el estado de la entidad envuelta por el proxy. Lo hace solo una vez en la vida de la sesión. La siguiente llamada a un método del proxy ya no irá a la base de datos, ya que el proxy ya no será inhabilitado por la llamada al método anterior. Y por supuesto necesita consultar la base de datos. ¿Cómo podría obtener datos de la base de datos sin consultarlos? La ventaja de los proxies perezosos es precisamente que recupera el estado solo si es necesario y cuando es necesario. Si sabe de antemano que necesitará el tipo de persona, entonces no use un proxy perezoso o use una consulta que cargue a la persona y su tipo en una sola consulta. Tu decides.