java - saveorupdate - sessionfactory save or update
Comportamiento de Hibernate saveOrUpdate (5)
Como se indica here , saveOrUpdate
guarda una instancia transitoria generando un nuevo identificador o actualiza / vuelve a conectar las instancias separadas asociadas con su identificador actual. Más específicamente, lo hace:
- si el objeto ya es persistente en esta sesión, no hagas nada
- si otro objeto asociado con la sesión tiene el mismo identificador, lanza una excepción
- si el objeto no tiene propiedad de identificador,
save()
- si el identificador del objeto tiene el valor asignado a un objeto recién instanciado, guárdelo ()
- si el objeto tiene una
<version>
o<timestamp>
, y el valor de la propiedad de la versión es - el mismo valor asignado a un objeto recién instanciado,
save()
- de lo contrario,
update()
el objeto
¿Alguien sabe cómo Hibernate sabe si INSERTAR o ACTUALIZAR un valor en la base de datos cuando se llama a session.saveOrUpdate()
?
Hasta ahora, solo he determinado que no depende de la información en el caché, y que la existencia de la entidad en la base de datos está determinada por la clave primaria.
Cuando use .saveOrUpdate()
Hibernate comprobará si el objeto es transitorio (no tiene ninguna propiedad de identificador) y, de ser así, lo hará persistente al generarlo y asignarlo a la sesión. Si el objeto ya tiene un identificador, realizará .update()
.
De la documentation :
saveOrUpdate () hace lo siguiente:
- si el objeto ya es persistente en esta sesión, no hagas nada
- si otro objeto asociado con la sesión tiene el mismo identificador, lanza una excepción
- si el objeto no tiene propiedad de identificador, guárdelo ()
- si el identificador del objeto tiene el valor asignado a un objeto recién instanciado, guárdelo ()
- si el objeto tiene una versión con un o y el valor de la propiedad de la versión es el mismo valor asignado a un objeto recién instanciado, save () de lo contrario actualizará () el objeto
Esto se hace en base al valor de la clave primaria. Si la clave principal no está definida, su valor predeterminado será 0 para las claves sustitutas numéricas y se realizará el save
. Si la clave principal está completa, invocará una update
.
Si alguien no entiende realmente en teoría, entonces hay un código
MyModel sent = myDao.myDaoImpl(id);
if(sent == null){
sent = **new MyModel();** // new Object
sent.setXX(id);
sent.setYY("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Insert will be called
}else if(! "Yes".equalsIgnoreCase(sent.getFlag())){
sent.setXX("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Update will be called
}
Tal vez sea útil citar la Biblia de Hibernate ( Java Persistence with Hibernate, 2nd ed. , Página 528):
Los usuarios más experimentados de Hibernate usan
saveOrUpdate()
exclusivamente; es mucho más fácil dejar que Hibernate decida qué es nuevo y qué es viejo, especialmente en una red más compleja de objetos con estado mixto. La única desventaja (no realmente grave) del exclusivosaveOrUpdate()
es que a veces no puede adivinar si una instancia es vieja o nueva sin activar unSELECT
en la base de datos, por ejemplo, cuando una clase se asigna con una clave compuesta natural y ninguna propiedad de versión o marca de tiempo.¿Cómo detecta Hibernate qué instancias son antiguas y cuáles son nuevas? Una gama de opciones está disponible. Hibernate supone que una instancia es una instancia transitoria no guardada si:
- La propiedad del identificador es
null
.- La propiedad de versión o marca de tiempo (si existe) es
null
.- Una nueva instancia de la misma clase persistente, creada internamente por Hibernate, tiene los mismos valores de identificador de base de datos que la instancia dada.
- Proporciona un
unsaved-value
en el documento de mapeo para la clase, y el valor de la propiedad del identificador coincide. El atributo deunsaved-value
también está disponible para los elementos de mapeo de la versión y la marca de tiempo.- Los datos de entidad con el mismo valor de identificador no se encuentran en la memoria caché de segundo nivel.
- Usted suministra una implementación u
org.hibernate.Interceptor
y devuelveBoolean.TRUE
desdeInterceptor.isUnsaved()
después de verificar la instancia en su código.