Aquí está mi comprensión de los métodos. Principalmente, estos se basan en la API, ya que no uso todos estos en la práctica.
saveOrUpdate Las
llamadas se guardan o actualizan según algunas comprobaciones. Por ejemplo, si no existe un identificador, se llama guardar. De lo contrario, se llama a la actualización.
guardar
Persiste una entidad. Asignará un identificador si no existe uno. Si uno lo hace, esencialmente está haciendo una actualización. Devuelve el ID generado de la entidad.
actualizar
Intenta persistir la entidad utilizando un identificador existente. Si no existe un identificador, creo que se produce una excepción.
saveOrUpdateCopy
Esto está en desuso y ya no debe usarse. En cambio hay ...
fusionar
Ahora aquí es donde mi conocimiento comienza a flaquear. Lo importante aquí es la diferencia entre entidades transitorias, separadas y persistentes. Para obtener más información sobre los estados del objeto, eche un vistazo aquí . Con guardar y actualizar, se trata de objetos persistentes. Están vinculados a una sesión para que Hibernate sepa lo que ha cambiado. Pero cuando tiene un objeto transitorio, no hay sesión involucrada. En estos casos, debe utilizar la combinación para actualizaciones y persistir para guardar.
persistir
Como se mencionó anteriormente, esto se usa en objetos transitorios. No devuelve la ID generada.
fuente
update
un objeto transitorio está bien, no obtuve una excepción.Consulte el Foro de Hibernate para obtener una explicación de las sutiles diferencias entre persistir y guardar. Parece que la diferencia es el momento en que finalmente se ejecuta la instrucción INSERT. Como guardar devuelve el identificador, la instrucción INSERT tiene que ejecutarse instantáneamente independientemente del estado de la transacción (que generalmente es algo malo). Persist no ejecutará ninguna declaración fuera de la transacción actualmente en ejecución solo para asignar el identificador. Save / Persist funciona en instancias transitorias , es decir, instancias que todavía no tienen un identificador asignado y, como tales, no se guardan en la base de datos.
Actualizar y combinar funcionan en instancias separadas , es decir, instancias que tienen una entrada correspondiente en la base de datos, pero que actualmente no están conectadas (o gestionadas por) una sesión. La diferencia entre ellos es lo que le sucede a la instancia que se pasa a la función. La actualización intenta volver a conectar la instancia, lo que significa que no debe haber otra instancia de la entidad persistente conectada a la sesión en este momento, de lo contrario, se genera una excepción. sin embargo, merge solo copia todos los valores a una instancia persistente en la sesión (que se cargará si no está cargada actualmente). El objeto de entrada no se modifica. Así que fusionar es más general que actualizar, pero puede usar más recursos.
fuente
save() - If an INSERT has to be executed to get the identifier, then this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is problematic in a long-running conversation with an extended Session/persistence context.
¿Puede decirme cómo puede ocurrir un inserto fuera de una sesión y por qué es malo?INSERT
. En consecuencia, en esos casos no puede devolver un identificador en este momento sin tenerlo generado y para generarlo debe ejecutarloINSERT
ahora . Dado que una transacción de larga duración no se ejecuta en este momento, sino solo en commit, la única forma de ejecutar elINSERT
ahora es ejecutarla fuera del tx.Este enlace explica de buena manera:
http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/
Todos tenemos esos problemas con los que nos encontramos con poca frecuencia como para que cuando los volvamos a ver, sepamos que hemos resuelto esto, pero no podemos recordar cómo.
La excepción NonUniqueObjectException lanzada cuando se usa Session.saveOrUpdate () en Hibernate es una de las mías. Agregaré nueva funcionalidad a una aplicación compleja. Todas mis pruebas unitarias funcionan bien. Luego, al probar la interfaz de usuario, al intentar guardar un objeto, empiezo a recibir una excepción con el mensaje "ya se ha asociado un objeto diferente con el mismo valor de identificador a la sesión". Aquí hay un código de ejemplo de Java Persistence con Hibernate.
Para comprender la causa de esta excepción, es importante comprender los objetos separados y lo que sucede cuando llama a saveOrUpdate () (o simplemente actualiza ()) en un objeto separado.
Cuando cerramos una sesión de Hibernate individual, los objetos persistentes con los que estamos trabajando se separan. Esto significa que los datos todavía están en la memoria de la aplicación, pero Hibernate ya no es responsable del seguimiento de los cambios en los objetos.
Si luego modificamos nuestro objeto separado y queremos actualizarlo, tenemos que volver a colocar el objeto. Durante ese proceso de reinstalación, Hibernate verificará si hay otras copias del mismo objeto. Si encuentra alguno, tiene que decirnos que ya no sabe cuál es la copia "real". Quizás se hicieron otros cambios a esas otras copias que esperamos que se guarden, pero Hibernate no las conoce porque no las estaba administrando en ese momento.
En lugar de guardar datos posiblemente malos, Hibernate nos informa sobre el problema a través de NonUniqueObjectException.
Entonces, ¿qué vamos a hacer? En Hibernate 3, tenemos merge () (en Hibernate 2, use saveOrUpdateCopy ()). Este método obligará a Hibernate a copiar cualquier cambio de otras instancias separadas en la instancia que desea guardar y, por lo tanto, fusiona todos los cambios en la memoria antes de guardar.
Es importante tener en cuenta que la combinación devuelve una referencia a la versión recién actualizada de la instancia. No está volviendo a asociar el elemento a la sesión. Si prueba por ejemplo la igualdad (item == item3), encontrará que devuelve falso en este caso. Probablemente desee trabajar con el elemento 3 a partir de ahora.
También es importante tener en cuenta que la API de persistencia de Java (JPA) no tiene un concepto de objetos separados y reenganchados, y utiliza EntityManager.persist () y EntityManager.merge ().
En general, descubrí que cuando utilizo Hibernate, saveOrUpdate () suele ser suficiente para mis necesidades. Por lo general, solo necesito usar merge cuando tengo objetos que pueden tener referencias a objetos del mismo tipo. Más recientemente, la causa de la excepción estaba en el código que validaba que la referencia no era recursiva. Estaba cargando el mismo objeto en mi sesión como parte de la validación, causando el error.
¿Dónde has encontrado este problema? ¿La fusión funcionó para usted o necesitaba otra solución? ¿Prefiere usar siempre la combinación o prefiere usarla solo según sea necesario para casos específicos?
fuente
En realidad, la diferencia entre hibernar
save()
ypersist()
métodos depende de la clase de generador que estamos usando.Si se asigna nuestra clase generador, entonces no hay diferencia entre
save()
epersist(
) métodos. Debido a que el generador 'asignado' significa, como programador, necesitamos dar el valor de la clave primaria para guardarlo en la base de datos correcta [Espero que conozca este concepto de generador] En caso de que no sea una clase de generador asignada, suponga que si nuestro nombre de clase de generador es Incremento significa hibernate sí mismo asignará el valor de ID de la clave primaria en la base de datos derecha [aparte del generador asignado, hibernate solo se usa para cuidar el valor de ID de la clave primaria recordar], por lo que en este caso si llamamossave()
opersist()
método, insertará el registro en la base de datos normalmente Pero escuche, elsave()
método puede devolver el valor de identificación de la clave primaria que se genera por hibernación y podemos verlo porEn este mismo caso,
persist()
nunca devolverá ningún valor al cliente.fuente
Encontré un buen ejemplo que muestra las diferencias entre todos los métodos de guardado de hibernación:
http://www.journaldev.com/3481/hibernate-session-merge-vs-update-save-saveorupdate-persist-example
En resumen, de acuerdo con el enlace anterior:
salvar()
persistir()
saveOrUpdate ()
Se puede usar con o sin la transacción, y al igual que save (), si se usa sin la transacción, las entidades mapeadas no se guardarán en;
Resultados en consultas de inserción o actualización basadas en los datos proporcionados. Si los datos están presentes en la base de datos, se ejecuta la consulta de actualización.
actualizar()
unir()
También para ejemplos prácticos de todo esto, consulte el enlace que mencioné anteriormente, muestra ejemplos de todos estos métodos diferentes.
fuente
Como expliqué en este artículo , debe preferir los métodos JPA la mayor parte del tiempo y las
update
tareas de procesamiento por lotes.Una entidad JPA o Hibernate puede estar en uno de los siguientes cuatro estados:
La transición de un estado a otro se realiza a través de los métodos EntityManager o Session.
Por ejemplo, el JPA
EntityManager
proporciona los siguientes métodos de transición de estado de entidad.Hibernate
Session
implementa todos losEntityManager
métodos JPA y proporciona algunos métodos adicionales de transición de estado de entidad comosave
,saveOrUpdate
yupdate
.Persistir
Para cambiar el estado de una entidad de Transitoria (Nueva) a Administrada (Persistente), podemos usar el
persist
método ofrecido por el JPAEntityManager
que también es heredado por el HibernateSession
.Por lo tanto, al ejecutar el siguiente caso de prueba:
Hibernate genera las siguientes instrucciones SQL:
Observe que
id
se asigna antes de adjuntar laBook
entidad al contexto de persistencia actual. Esto es necesario porque las entidades administradas se almacenan en unaMap
estructura donde la clave está formada por el tipo de entidad y su identificador y el valor es la referencia de la entidad. Esta es la razón por la cual el JPAEntityManager
y el HibernateSession
se conocen como el caché de primer nivel.Al llamar
persist
, la entidad solo se adjunta al contexto de persistencia actualmente en ejecución, y el INSERT puede posponerse hasta queflush
se llame.La única excepción es el generador de IDENTIDAD que activa el INSERTAR de inmediato, ya que esa es la única forma en que puede obtener el identificador de la entidad. Por esta razón, Hibernate no puede insertar por lotes para entidades que usan el generador IDENTITY. Para obtener más detalles sobre este tema, consulte este artículo .
Salvar
El
save
método específico de Hibernate es anterior a JPA y ha estado disponible desde el comienzo del proyecto Hibernate.Para ver cómo funciona el
save
método, considere el siguiente caso de prueba:Al ejecutar el caso de prueba anterior, Hibernate genera las siguientes instrucciones SQL:
Como puede ver, el resultado es idéntico a la
persist
llamada al método. Sin embargo, a diferenciapersist
, elsave
método devuelve el identificador de entidad.Para más detalles, mira este artículo .
Actualizar
El
update
método específico de Hibernate está destinado a evitar el mecanismo de verificación sucio y forzar una actualización de la entidad en el momento del vaciado.Para ver cómo funciona el
update
método, considere el siguiente ejemplo que persiste unaBook
entidad en una transacción, luego la modifica mientras la entidad está en el estado desconectado, y fuerza la ACTUALIZACIÓN de SQL utilizando laupdate
llamada al método.Al ejecutar el caso de prueba anterior, Hibernate genera las siguientes instrucciones SQL:
Observe que
UPDATE
se ejecuta durante el vaciado del contexto de persistencia, justo antes de la confirmación, y es por eso que elUpdating the Book entity
mensaje se registra primero.Utilizando
@SelectBeforeUpdate
para evitar actualizaciones innecesariasAhora, la ACTUALIZACIÓN siempre se ejecutará, incluso si la entidad no se cambió mientras estaba en el estado desconectado. Para evitar esto, puede usar la
@SelectBeforeUpdate
anotación Hibernate que activará unaSELECT
declaración que se obtiene yloaded state
que luego utiliza el mecanismo de verificación sucio.Entonces, si anotamos la
Book
entidad con la@SelectBeforeUpdate
anotación:Y ejecute el siguiente caso de prueba:
Hibernate ejecuta las siguientes instrucciones SQL:
Tenga en cuenta que, esta vez, no se
UPDATE
ejecuta desde que el mecanismo de comprobación sucia de Hibernate ha detectado que la entidad no se modificó.SaveOrUpdate
El
saveOrUpdate
método específico de Hibernate es solo un alias parasave
yupdate
.Ahora, puede usar
saveOrUpdate
cuando desea persistir una entidad o forzar unaUPDATE
como se ilustra en el siguiente ejemplo.Cuidado con el
NonUniqueObjectException
Un problema que puede ocurrir con
save
,update
ysaveOrUpdate
es si el Contexto de persistencia ya contiene una referencia de entidad con la misma identificación y del mismo tipo que en el siguiente ejemplo:Ahora, al ejecutar el caso de prueba anterior, Hibernate va a lanzar un
NonUniqueObjectException
porque el segundoEntityManager
ya contiene unaBook
entidad con el mismo identificador al que pasamosupdate
, y el Contexto de persistencia no puede contener dos representaciones de la misma entidad.Unir
Para evitarlo
NonUniqueObjectException
, debe usar elmerge
método ofrecido por JPAEntityManager
y heredado por HibernateSession
también.Como se explica en este artículo , el
merge
obtiene una nueva instantánea de entidad de la base de datos si no se encuentra ninguna referencia de entidad en el Contexto de persistencia, y copia el estado de la entidad separada que se pasó almerge
método.Para ver cómo funciona el
merge
método, considere el siguiente ejemplo que persiste a unaBook
entidad en una transacción, luego la modifica mientras la entidad está en el estado separado y pasa la entidad separada amerge
en un contexto de persistencia posterior.Al ejecutar el caso de prueba anterior, Hibernate ejecutó las siguientes instrucciones SQL:
Observe que la referencia de entidad devuelta por
merge
es diferente de la separada que pasamos almerge
método.Ahora, aunque debería preferir usar JPA
merge
al copiar el estado de la entidad separada, el extraSELECT
puede ser problemático al ejecutar una tarea de procesamiento por lotes.Por esta razón, debería preferir usar
update
cuando esté seguro de que no hay una referencia de entidad ya asociada al Contexto de persistencia actualmente en ejecución y que la entidad separada se ha modificado.Para obtener más detalles sobre este tema, consulte este artículo. .
Conclusión
Para persistir una entidad, debe usar el
persist
método JPA . Para copiar el estado de la entidad separada, semerge
debe preferir. Elupdate
método es útil solo para tareas de procesamiento por lotes. Lossave
ysaveOrUpdate
son solo aliasupdate
y probablemente no debería usarlos en absoluto.Algunos desarrolladores llaman
save
incluso cuando la entidad ya está administrada, pero esto es un error y desencadena un evento redundante ya que, para las entidades administradas, la ACTUALIZACIÓN se maneja automáticamente en el momento de descarga del contexto de Persistencia.Para más detalles, mira este artículo .
fuente
Tenga en cuenta que si llama a una actualización en un objeto separado, siempre se realizará una actualización en la base de datos, ya sea que haya cambiado el objeto o no. Si no es lo que desea, debe usar Session.lock () con LockMode.None.
Debe llamar a la actualización solo si el objeto se cambió fuera del alcance de su sesión actual (cuando está en modo separado).
fuente
Ninguna de las siguientes respuestas son correctas. Todos estos métodos parecen ser iguales, pero en la práctica hacen cosas absolutamente diferentes. Es difícil hacer comentarios cortos. Es mejor dar un enlace a la documentación completa sobre estos métodos: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html
fuente
Ninguna de las respuestas anteriores está completa. Aunque la respuesta de Leo Theobald parece la respuesta más cercana.
El punto básico es cómo hibernate trata con estados de entidades y cómo los maneja cuando hay un cambio de estado. Todo se debe ver con respecto a los rubores y los compromisos, que todo el mundo parece haber ignorado por completo.
NUNCA USE EL MÉTODO DE AHORRO de HIBERNATE. ¡OLVIDEN QUE INCLUSO EXISTE EN HIBERNATE!
Persistir
Como todos explicaron, Persist básicamente hace una transición de una entidad del estado "Transitorio" al "Administrado". En este punto, un granizado o una confirmación pueden crear una declaración de inserción. Pero la entidad aún permanecerá en estado "Administrado". Eso no cambia con el rubor.
En este punto, si "persiste" nuevamente no habrá cambios. Y no habrá más salvaciones si tratamos de persistir en una entidad persistente.
La diversión comienza cuando tratamos de desalojar a la entidad.
Un desalojo es una función especial de Hibernate que hará la transición de la entidad de "Administrado" a "Independiente". No podemos llamar a persistir en una entidad separada. Si hacemos eso, entonces Hibernate genera una excepción y toda la transacción se revierte en commit.
Combinar vs Actualizar
Estas son 2 funciones interesantes que hacen cosas diferentes cuando se tratan de diferentes maneras. Ambos intentan hacer la transición de la entidad del estado "Separado" al estado "Administrado". Pero hacerlo de manera diferente.
Comprenda el hecho de que Separado significa una especie de estado "fuera de línea". y administrado significa estado "en línea".
Observe el siguiente código:
Cuando haces esto? ¿Qué piensas tú que sucederá? Si dijo que esto generará una excepción, entonces está en lo correcto. Esto generará una excepción porque la fusión ha funcionado en el objeto de entidad, que es el estado separado. Pero no altera el estado del objeto.
Detrás de escena, la fusión generará una consulta de selección y básicamente devolverá una copia de la entidad que está en estado adjunto. Observe el siguiente código:
El ejemplo anterior funciona porque la fusión ha traído una nueva entidad al contexto que está en estado persistente.
Cuando se aplica con Actualización, lo mismo funciona bien porque la actualización en realidad no trae una copia de la entidad como fusión.
Al mismo tiempo, en el seguimiento de depuración podemos ver que la actualización no ha generado una consulta SQL de seleccionar como combinar.
Eliminar
En el ejemplo anterior, utilicé eliminar sin hablar de eliminar. Eliminar básicamente hará que la entidad pase del estado administrado al estado "eliminado". Y cuando se sonroja o se compromete, emitirá un comando de eliminación para almacenar.
Sin embargo, es posible devolver la entidad al estado "administrado" desde el estado "eliminado" utilizando el método de persistencia.
Espero que la explicación anterior aclare cualquier duda.
fuente