Respuestas:
persist()
Está bien definido. Hace que una instancia transitoria sea persistente. Sin embargo, no garantiza que el valor del identificador se asignará a la instancia persistente de inmediato, la asignación puede ocurrir en el momento del vaciado. La especificación no dice eso, que es el problema que tengopersist()
.
persist()
también garantiza que no ejecutará una instrucción INSERT si se llama fuera de los límites de la transacción. Esto es útil en conversaciones de larga duración con un contexto extendido de sesión / persistencia.Se
persist()
requiere un método como .
save()
no garantiza lo mismo, devuelve un identificador, y si se debe ejecutar un INSERT para obtener el identificador (por ejemplo, generador de "identidad", no "secuencia"), este INSERT se produce de inmediato, sin importar si está dentro o fuera una transacción Esto no es bueno en una conversación de larga duración con un contexto extendido de sesión / persistencia.
He realizado una buena investigación sobre save () vs persist (), incluida la ejecución en mi máquina local varias veces. Todas las explicaciones anteriores son confusas y no son correctas. Comparé el guardar () y el persistir () a continuación después de una investigación exhaustiva.
Save()
Serializable
tipo de retorno.Persist()
generated id
a la entidad que persistesession.persist()
para un objeto separado arrojará PersistentObjectException
ya que no está permitido.Todos estos son probados / probados Hibernate v4.0.1
.
Save()
?
Hice algunas pruebas simuladas para registrar la diferencia entre save()
y persist()
.
Parece que ambos métodos se comportan igual cuando se trata de una entidad transitoria, pero difieren cuando se trata de una entidad separada.
Para el siguiente ejemplo, tome EmployeeVehicle como una Entidad con PK, vehicleId
que es un valor generado y vehicleName
como una de sus propiedades.
Ejemplo 1: Manejo de objetos transitorios
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();
Resultado:
select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)
Tenga en cuenta que el resultado es el mismo cuando obtiene un objeto ya persistente y lo guarda
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity); -------> **instead of session.update(entity);**
// session.persist(entity);
Repita lo mismo usando persist(entity)
y resultará igual con un nuevo Id (digamos 37, honda);
Ejemplo 2: Tratar con objeto separado
// Session 1
// Get the previously saved Vehicle Entity
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();
// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it
// (i) Using Save() to persist a detached object
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();
Resultado: es posible que espere que el Vehículo con id: 36 obtenido en la sesión anterior se actualice con el nombre "Toyota". Pero lo que sucede es que una nueva entidad se guarda en la base de datos con un nuevo Id generado para y Nombre como "Toyota"
select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)
Uso de persistir para persistir entidad separada
// (ii) Using Persist() to persist a detached
// Session 1
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();
// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();
Resultado:
Exception being thrown : detached entity passed to persist
Por lo tanto, siempre es mejor usar Persist () en lugar de Save () ya que guardar debe usarse con cuidado cuando se trata de objetos Transient.
Nota importante: en el ejemplo anterior, el pk de la entidad del vehículo es un valor generado, por lo que cuando se usa save () para persistir una entidad separada, hibernate genera una nueva identificación para persistir. Sin embargo, si este pk no es un valor generado, se genera una excepción que indica la violación de la clave.
Esta pregunta tiene algunas buenas respuestas sobre los diferentes métodos de persistencia en Hibernate. Para responder a su pregunta directamente, con save () la instrucción de inserción se ejecuta inmediatamente, independientemente del estado de la transacción. Devuelve la clave insertada para que pueda hacer algo como esto:
long newKey = session.save(myObj);
Por lo tanto, use save () si necesita un identificador asignado a la instancia persistente de inmediato.
Con persist (), la instrucción de inserción se ejecuta en una transacción, no necesariamente de forma inmediata. Esto es preferible en la mayoría de los casos.
Use persist () si no necesita que la inserción se realice fuera de secuencia con la transacción y no necesita que se devuelva la clave insertada.
Estas son las diferencias que pueden ayudarlo a comprender las ventajas de los métodos de persistencia y guardado:
El método persist () no garantiza que el valor del identificador se asignará al estado persistente de inmediato, la asignación puede ocurrir en el momento del vaciado.
El método persist () no ejecutará una consulta de inserción si se llama fuera de los límites de la transacción. Mientras, el método save () devuelve un identificador para que una consulta de inserción se ejecute inmediatamente para obtener el identificador, sin importar si está dentro o fuera de una transacción.
El método de persistencia se llama fuera de los límites de la transacción, es útil en conversaciones de larga duración con un contexto de sesión extendido. Por otro lado, el método de guardar no es bueno en una conversación de larga duración con un contexto de sesión extendido.
Quinta diferencia entre el método guardar y persistir en Hibernate: persist es compatible con JPA, mientras que guardar solo es compatible con Hibernate.
Puede ver el ejemplo de trabajo completo en la publicación Diferencia entre el método de guardar y persistir en Hibernate
save (): como sugiere el nombre del método, hibernate save () se puede usar para guardar la entidad en la base de datos. Podemos invocar este método fuera de una transacción. Si usamos esto sin transacción y tenemos una conexión en cascada entre entidades, solo se salvará la entidad primaria a menos que lancemos la sesión.
persistir (): la persistencia de Hibernate es similar a guardar (con transacción) y agrega el objeto de entidad al contexto persistente, por lo que se realiza un seguimiento de cualquier cambio adicional. Si las propiedades del objeto se cambian antes de que se confirme la transacción o se vacíe la sesión, también se guardará en la base de datos. Además, podemos usar el método persist () solo dentro del límite de una transacción, por lo que es seguro y se ocupa de los objetos en cascada. Finalmente, persistir no devuelve nada, por lo que debemos usar el objeto persistente para obtener el valor del identificador generado.
Aquí está la diferencia:
salvar:
Persistir:
La regla básica dice que:
Para entidades con identificador generado:
save (): devuelve el identificador de una entidad inmediatamente además de hacer que el objeto sea persistente. Por lo tanto, una consulta de inserción se activa de inmediato.
persistir (): devuelve el objeto persistente. No tiene ninguna obligación de devolver el identificador de inmediato, por lo que no garantiza que el inserto se disparará de inmediato. Puede disparar un inserto de inmediato, pero no está garantizado. En algunos casos, la consulta puede dispararse inmediatamente, mientras que en otros puede dispararse en el momento de la descarga de la sesión.
Para entidades con identificador asignado:
save (): devuelve el identificador de una entidad de inmediato. Como el identificador ya está asignado a la entidad antes de llamar a guardar, la inserción no se activa de inmediato. Se dispara a la hora de descarga de la sesión.
persistir (): igual que guardar. También dispara el inserto en el momento de descarga.
Supongamos que tenemos una entidad que usa un identificador generado de la siguiente manera:
@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
@Id
@Column(name = "USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name = "USER_NAME")
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
salvar() :
Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserName("Gaurav");
session.save(user); // Query is fired immediately as this statement is executed.
session.getTransaction().commit();
session.close();
persistir ():
Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserName("Gaurav");
session.persist(user); // Query is not guaranteed to be fired immediately. It may get fired here.
session.getTransaction().commit(); // If it not executed in last statement then It is fired here.
session.close();
Ahora suponga que tenemos la misma entidad definida de la siguiente manera sin que el campo id haya generado una anotación, es decir, la ID se asignará manualmente.
@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
@Id
@Column(name = "USER_ID")
private int userId;
@Column(name = "USER_NAME")
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
para guardar ():
Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.save(user); // Query is not fired here since id for object being referred by user is already available. No query need to be fired to find it. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();
para persistir ():
Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.persist(user); // Query is not fired here.Object is made persistent. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();
Los casos anteriores fueron ciertos cuando se llamó a guardar o persistir desde una transacción.
Los otros puntos de diferencia entre guardar y persistir son:
Se puede llamar a save () fuera de una transacción. Si se utiliza el identificador asignado, ya que el ID ya está disponible, por lo que no se activa ninguna consulta de inserción. La consulta solo se activa cuando la sesión se vacía.
Si se utiliza el identificador generado, entonces, dado que la identificación debe generarse, la inserción se dispara inmediatamente. Pero solo salva a la entidad primaria. Si la entidad tiene algunas entidades en cascada, entonces esas no se guardarán en db en este momento. Se guardarán cuando la sesión se vacíe.
Si persist () está fuera de una transacción, la inserción solo se activa cuando se vacía la sesión, sin importar qué tipo de identificador (generado o asignado) se utilice.
Si se llama guardar sobre un objeto persistente, la entidad se guarda mediante la consulta de actualización.
En realidad, la diferencia entre los métodos hibernate save () y persist () depende de la clase de generador que estemos usando.
Si se asigna nuestra clase de generador, entonces no hay diferencia entre los métodos save () y persist (). 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] hibernate en sí asignará el valor de ID de la clave primaria a la base de datos [aparte del generador asignado, hibernate solo se usa para cuidar el valor de ID de la clave primaria recordar], así que en este caso si llamamos al método save () o persist (), entonces insertará el registro en la base de datos normalmente.
Pero aquí, lo que pasa es que el método save () puede devolver el valor de identificación de la clave primaria que genera hibernate y podemos verlo por
s = session.save (k);
En este mismo caso, persist () nunca devolverá ningún valor al cliente, devuelve el tipo void.
persist () también garantiza que no ejecutará una instrucción INSERT si se llama fuera de los límites de la transacción.
mientras que en save (), INSERT ocurre inmediatamente, sin importar si está dentro o fuera de una transacción.
Respondió completamente sobre la base del tipo de "generador" en la identificación mientras almacenaba cualquier entidad. Si el valor para el generador está "asignado", lo que significa que está proporcionando la ID. Entonces no hace diferencia en hibernar para guardar o persistir. Puedes ir con cualquier método que desees. Si el valor no está "asignado" y está utilizando save (), obtendrá la ID como retorno de la operación save ().
Otra comprobación es si está realizando la operación fuera del límite de transacción o no. Porque persist () pertenece a JPA mientras save () para hibernar. Por lo tanto, el uso de persist () fuera de los límites de la transacción no permitirá hacerlo y generará excepciones relacionadas con persistente. mientras que con save () no existe tal restricción y uno puede ir con la transacción DB a través de save () fuera del límite de la transacción.