2009-03-04 9 views
83

Desde la API, pude ver que tiene algo que ver con el proxy. Pero no pude encontrar mucha información sobre el proxy y no entiendo la diferencia entre llamar a session.get y session.load. ¿Podría alguien explicarme o dirigirme a una página de referencia?Hibernate: Diferencia entre session.get y session.load

Gracias!

Respuesta

111

Desde el Hibernate forum:

Este del libro de hibernación en acción. Bueno leer este ..


Recuperando objetos por identificador El siguiente fragmento de código de Hibernate recupera un objeto de usuario de la base de datos:

User user = (User) session.get(User.class, userID); 

El método get() es especial porque el identificador identifica de manera única una sola instancia de de una clase. Por lo tanto, es común que las aplicaciones usen el identificador como un identificador conveniente para un objeto persistente. La recuperación por identificador puede usar el caché al recuperar un objeto, evitando que se golpee una base de datos si el objeto ya está en caché. Hibernate proporciona también un método de carga():

User user = (User) session.load(User.class, userID); 

La carga() método es más; get() se agregó a la API de Hibernate debido a la solicitud del usuario . La diferencia es trivial:

Si la carga() no puede encontrar el objeto en la caché o base de datos, una excepción es lanzada . El método load() nunca devuelve null. El método get() devuelve null si no se puede encontrar el objeto.

El método load() puede devolver un proxy en lugar de una instancia real persistente. Un proxy es un marcador de posición que desencadena la carga del objeto real cuando se accede al por primera vez; En el por otro lado, get() nunca devuelve un proxy. Elegir entre get() y load() es fácil: si está seguro de que existe el objeto persistente y la inexistencia se considerará excepcional, load() es una buena opción . Si no está seguro de que haya una instancia persistente con el identificador dado, use get() y pruebe el valor de retorno para ver si es nulo. Usar load() tiene una implicación adicional: la aplicación puede recuperar una referencia válida (un proxy) a una instancia persistente sin golpear la base de datos para recuperar su estado persistente. Por lo tanto, load() no puede lanzar una excepción cuando no encuentra el objeto persistente en el caché o la base de datos; la excepción se lanzaría más tarde, cuando se accede al proxy . Por supuesto, recuperar un objeto por identificador no es tan flexible como usar consultas arbitrarias .

+1

Estoy depurando un problema ahora mismo donde session.Get () está devolviendo un proxy! –

+7

¡Muchas gracias! La parte de dinero para mí fue: "Si load() no puede encontrar el objeto en el caché o la base de datos, se lanza una excepción. El método get() devuelve null si el objeto no se puede encontrar". – Chris

+15

El JavaDoc para Session.get dice: Devuelve la instancia persistente de la clase de entidad dada con el identificador dado, o nulo si no hay tal instancia persistente. (Si la instancia, o un proxy para la instancia, ya está asociado a la sesión, devuelva esa instancia o proxy.) Entonces la sección del libro que dice: "Por otro lado, get() nunca devuelve un proxy". no es correcto. – Vicky

14

Bueno, en nhibernate al menos, session.Get (id) cargará el objeto de la base de datos, mientras que session.Load (id) solo creará un objeto proxy sin salir de su servidor. Funciona igual que cualquier otra propiedad de carga lenta en sus POCO (o POJOs :). A continuación, puede usar este proxy como una referencia al objeto en sí para crear relaciones, etc.

Piense en ello como tener un objeto que solo conserva el Id y que cargará el resto si alguna vez lo necesita. Si solo lo está pasando para crear relaciones (como FK), la identificación es todo lo que necesitará.

+0

, por lo que quiere decir que load (id) primero presionará la base de datos para comprobar si es válida o no y devolverá el objeto proxy y cuando se acceda a las propiedades de este objeto, vuelve a la base de datos. ¿No es un escenario poco probable? dos consultas para cargar un solo objeto? – faisalbhagat

+0

No, load (id) no validará la identificación en absoluto así que no hay viajes de ida y vuelta a la base de datos. Úselo solo cuando esté seguro de estar seguro de que es válido. –

9

session.load() siempre devolverá un "proxy" (término Hibernate) sin presionar la base de datos. En Hibernate, proxy es un objeto con el valor del identificador dado, sus propiedades aún no se han inicializado, simplemente se ve como un objeto falso temporal. Si no se encuentra ninguna fila, arrojará una ObjectNotFoundException.

session.get() siempre golpea la base de datos y devuelve el objeto real, un objeto que representa la fila de la base de datos, no el proxy. Si no se encuentra ninguna fila, devuelve nulo.

El rendimiento con estos métodos también hace diff. entre dos ...

0

También tenemos que tener cuidado al usar la carga ya que arrojará una excepción si el objeto no está presente. Tenemos que usarlo solo cuando estemos seguros de que ese objeto existe.

1

Una consecuencia indirecta del uso de "carga" en lugar de "obtener" es que el bloqueo optimista con un atributo de versión puede no funcionar como era de esperar. Si una carga simplemente crea un proxy y no lee de la base de datos, la propiedad de la versión no se carga. La versión solo se cargará cuando/luego se refiera a una propiedad en el objeto, lo que activará una selección. Mientras tanto, otra sesión puede actualizar el objeto, y su sesión no tendrá la versión original que necesita para realizar la verificación de bloqueo optimista, por lo que la actualización de la sesión sobrescribirá la actualización de la otra sesión sin previo aviso.

Aquí hay un intento de esbozar este escenario con dos sesiones trabajando con un objeto con el mismo identificador. Versión inicial para el objeto en el PP es 10.

Session 1     Session 2 
---------     --------- 
Load object 
Wait a while.. 
          Load object 
          Modify object property 
          [triggers db 'select' - 
          version read as 10] 
          Commit 
          [triggers db update, 
          version modified to 11] 
Modify object property 
    [triggers db 'select' - 
    version read as 11] 
Commit 
    [triggers db update, 
    version modified to 12] 

realidad Queremos sesión de 1 de cometer un error con una excepción bloqueo optimista, pero va a tener éxito aquí.

El uso de "obtener" en lugar de "cargar" soluciona el problema, porque get emitirá inmediatamente una selección, y los números de versión se cargarán en los momentos correctos para la comprobación de bloqueo optimista.

2

Un punto más extra ::

método get de la clase Session de Hibernate devuelve null si el objeto no se encuentra en la caché, así como en la base de datos. mientras que el método load() arroja ObjectNotFoundException si el objeto no se encuentra en el caché ni en la base de datos, pero nunca devuelve un valor nulo.

0

Una excelente explicación se encuentra en http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
Session.load():
siempre devolverá un “proxy” (Hibernate plazo) sin chocar con la base de datos.
En Hibernate, el proxy es un objeto con el valor del identificador dado, sus propiedades aún no se han inicializado, simplemente se ve como un objeto falso temporal.
Siempre devolverá un objeto proxy con el valor de identidad dado, incluso el valor de identidad no existe en la base de datos. Sin embargo, cuando intente inicializar un proxy recuperando sus propiedades de la base de datos, golpeará la base de datos con una instrucción select. Si no se encuentra una fila, se lanzará una ObjectNotFoundException.
session.get():
Siempre golpea la base de datos (si no se encuentra en el caché) y devuelve el objeto real, un objeto que representa la fila de la base de datos, no el proxy.
Si no se encuentra una fila, devuelve nulo.

0

load() no se puede encontrar el objeto desde el caché o la base de datos, se lanza una excepción y el método load() nunca devuelve null.

método get() devuelve nulo si no se puede encontrar el objeto. El método load() puede devolver un proxy en lugar de una instancia real persistente get() nunca devuelve un proxy.

Cuestiones relacionadas