2011-11-08 13 views
9

Estoy tratando de entender cuál es la diferencia en el objeto devuelto y el comportamiento de Hibernate 3.6 session.get() y session.load().Hibernate 3.6 - session.get() vs session.load()

Desde el javadoc:

get():

retorno persistente la instancia de la clase determinada entidad con el identificador dado , o null si no hay tal instancia persistente. (Si la instancia ya está asociada a la sesión, regresa esa instancia Este método no devuelve una instancia sin inicializar..)

carga():

retorno persistente la instancia de la clase de entidad dada con el identificador dado , suponiendo que exista la instancia. Este método podría devolver una instancia de proxy que se inicializa bajo demanda, cuando se accede a un método sin identificador .

Tengo tres preguntas:

  1. el Javadoc no dice cuándo podría volver load() un proxy - ¿hay alguna manera de saber de antemano?

  2. Cuando load() devuelve un proxy - esto significa load() no accedió a la base de datos, ¿estoy en lo correcto? Entonces, ¿qué ocurre si proporciono load() con un identificador que no existe en la base de datos? Ahora tendré en la sesión un proxy con una identificación inválida (sin obtener una excepción). Ahora quiero permitir que otra instancia persistente apunte a ese proxy: ¿funcionará? Para este escenario, no necesito inicializar el proxy, solo necesito su id (que aunque no es válido porque no está en la base de datos). Así que supongo que estoy preguntando si mi descripción es correcta, y siempre tengo que retirar el load() objeto devuelto con isInitialized() para asegurarme de que representa una entidad válida (o al menos un proxy válido), es decir, con un válido CARNÉ DE IDENTIDAD.

  3. Además, lo que sucede si load() devuelve un proxy, por lo que el proxy es la instancia que ya está asociada a la sesión. Luego, según la descripción de get(): "Si la instancia ya está asociada a la sesión, devuelva esa instancia". - Entonces, ¿get() devuelve el proxy? Dado que de acuerdo con la descripción de get(): "Este método nunca devuelve una instancia no inicializada".

Gracias!

ACTUALIZACIÓN

son los siguientes correcta?

(A) Creo que las dos load() y get() primero tratará de verificar el caché de sesión antes de ir a la base de datos - por lo que no sería correcto decir que cualquiera de ellos siempre da en la base de datos, o siempre devuelve un proxy.

(B) un proxy inicializado no es la misma que la instancia original, como se puede leer aquí: http://blog.xebia.com/2008/03/08/advanced-hibernate-proxy-pitfalls/

Respuesta

17

(1), (3):

Sí. Tiene razón. Tanto el load() como el get() verificará primero si hay una instancia con el mismo PK persistido en la sesión.

En caso afirmativo, solo devuelve esa instancia de la sesión. (Puede ser el proxy o la instancia real clase de entidad)

Si no, se load() crear y devolver un proxy mientras get() llegarán DB y devuelve instancia de la clase entidad real.

El objeto devuelto de ambos métodos se asociará y persistirá en la sesión posterior.

Por lo tanto, si el proxy de devolución get() o load() o la clase de entidad real depende de si usa get() o load() para obtener la instancia de la misma PK en la sesión actual por primera vez.

Puede prueba de este comportamiento mediante la realización de las siguientes pruebas:

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()); 

Si se trata de un proxy, el nombre de la clase impresa no será el mismo que el nombre real de la clase entidad. Simplemente cambie el orden de ejecución de load() y get() para ver el efecto.

(2):

Si la carga() devuelve un proxy, no tendrá acceso a la base de datos durante load() .La representación sólo se accede a la base de datos si se accede a sus propiedades asignadas, además de la PK y no hay casos con el mismo valor de PK asociado a la sesión.

Después de que el proxy acceda al DB, la instancia con el mismo PK del proxy se asociará con esa sesión. Así que cuando obtenga otras propiedades del proxy nuevamente o use get() para obtener la instancia para el mismo PK, no se accederá a la base de datos ya que los valores se pueden encontrar desde la sesión.

Por ejemplo:

/**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 

Si load() una instancia con el ID no válido y luego accede a las propiedades o llamar a un método (como isInitialized()) en este proxy, ObjectNotFoundException será lanzada. Por lo tanto, si puede capturar ObjectNotFoundException, significa que un proxy se carga con una ID no válida.

Si desea asegurarse de que el ID sea válido durante el tiempo de ejecución, debe usar get() y comprobar si la instancia devuelta es nula. load() es útil al establecer la restricción de clave externa. Ver this

+0

1.Pero si ya tenía una instancia inicializada (para este ID) en la sesión, ¿no devolvería esa instancia y no un proxy? Además, el javadoc dice: "Este método puede devolver una instancia de proxy" - no dice "este método siempre". 2. Es una especie de falla de diseño, ya que de acuerdo con lo que dices cuando tengo un proxy y quiero asegurarme de que representa una identificación real en DB (y siempre quiero asegurarlo), incluso si solo uso el proxy para indicarle otras instancias) - entonces no puedo saber que la ID que usé es válida hasta que la inicialice, pero en este caso, ¿por qué usar un proxy? – rapt

+0

3. ¿Quiere decir que 'get()' después de 'load()' devolverá un proxy inicializado, o solo una instancia inicializada? Dado que si es el último, entonces ahora tenemos en la sesión dos objetos que tienen el mismo ID (el proxy y la instancia). Por cierto, sé que es posible tener dos proxies que representen la misma ID de DB, como puede leer aquí: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/ debajo del texto " En segundo lugar, es posible romper el proxy ". - Ver más en ACTUALIZACIÓN en mi pregunta original. – rapt

+0

Sí. Tiene razón. Sus preguntas me ayudan a aclarar algunos malentendidos sobre 'get()' y 'load()'. Vea mi actualización, por favor –

Cuestiones relacionadas