Esto es de la sección 10.7. Detección automática del estado de la documentación de referencia de Hibernate:
saveOrUpdate () hace lo siguiente:
- si el objeto ya es persistente en esta sesión, no haga 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 está versionado (por una <version> o <timestamp>), y el valor de la propiedad de versión es el mismo valor asignado a un objeto recién instanciado, guárdelo ()
- de lo contrario, actualice () el objeto
y merge () es muy diferente:
- si hay una instancia persistente con el mismo identificador asociado actualmente con la sesión, copie el estado del objeto dado en la instancia persistente
- Si no hay una instancia persistente actualmente asociada con la sesión, intente cargarla desde la base de datos o cree una nueva instancia persistente.
- se devuelve la instancia persistente
- la instancia dada no se asocia con la sesión, permanece separada
Debe usar Merge () si está intentando actualizar objetos que en un momento se separaron de la sesión, especialmente si puede haber instancias persistentes de esos objetos actualmente asociados con la sesión. De lo contrario, usar SaveOrUpdate () en ese caso resultaría en una excepción.
SaveOrUpdateCopy
no es lo mismo queSaveOrUpdate
. No estoy seguro de si el interrogador quería compararMerge
el primero o el segundo.SaveOrUpdateCopy
es un método ahora obsoleto que se fusionó en NHibernate antes deMerge
ser importado.Según tengo entendido,
merge()
tomará un objeto que puede no estar asociado con la sesión actual y copiará su estado (valores de propiedad, etc.) a un objeto que sea asociado con la sesión actual (con el mismo valor / identificador PK, de curso).saveOrUpdate()
llamará a Guardar o Actualizar en su sesión, según el valor de identidad de un objeto determinado.fuente
SaveOrUpdateCopy()
ahora está obsoleto a partir de NHibernate 3.1.Merge()
debe usarse en su lugar.fuente
SaveOrUpdateCopy
que está marcadoObsolete
, noSaveOrUpdate
. Parece haber mucha confusión entre estos dos métodos diferentes en esta pregunta y las respuestas posteriores.** Update()**
: - si está seguro de que la sesión no contiene una instancia ya persistente con el mismo identificador, use la actualización para guardar los datos en hibernación
** Merge()**
: -si desea guardar sus modificaciones en cualquier momento sin conocer el estado de una sesión, utilice merge () en hibernación.
fuente
Encontré esto enlace que hizo un buen trabajo al explicar este tipo de excepción:
Lo que funcionó para mí es lo siguiente:
cascade="merge"
SaveOrUpdate
el objeto hijo / dependiente primero antes de asignarlo al objeto padre.SaveOrUpdate
el objeto padre.Sin embargo, esta solución tiene limitaciones. es decir, tienes que encargarte de salvar a tu hijo / objeto dependiente en lugar de dejar que hibernar lo haga por ti.
Si alguien tiene una mejor solución, me gustaría verla.
fuente
@Entity @Table(name="emp") public class Employee implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="emp_id") private int id; @Column(name="emp_name") private String name; @Column(name="salary") private int Salary; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSalary() { return Salary; } public void setSalary(int salary) { this.Salary = salary; } public int getId() { return id; } public void setId(int id) { this.id = id; } } public enum HibernateUtil { INSTANCE; HibernateUtil(){ buildSessionFactory(); } private SessionFactory sessionFactory=null; public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } private void buildSessionFactory() { Configuration configuration = new Configuration(); configuration.addAnnotatedClass (TestRefresh_Merge.Employee.class); configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver"); configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate"); configuration.setProperty("hibernate.connection.username", "root"); configuration.setProperty("hibernate.connection.password", "root"); configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect"); configuration.setProperty("hibernate.hbm2ddl.auto", "update"); configuration.setProperty("hibernate.show_sql", "true"); configuration.setProperty(" hibernate.connection.pool_size", "10"); /* configuration.setProperty(" hibernate.cache.use_second_level_cache", "true"); configuration.setProperty(" hibernate.cache.use_query_cache", "true"); configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider"); configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory"); */ // configuration StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()); sessionFactory = configuration.buildSessionFactory(builder.build()); setSessionFactory(sessionFactory); } public static SessionFactory getSessionFactoryInstance(){ return INSTANCE.getSessionFactory(); } } public class Main { public static void main(String[] args) { HibernateUtil util=HibernateUtil.INSTANCE; SessionFactory factory=util.getSessionFactory(); //save(factory); retrieve(factory); } private static void retrieve(SessionFactory factory) { Session sessionOne=factory.openSession(); Employee employee=(Employee)sessionOne.get(Employee.class, 5); sessionOne.close(); // detached Entity employee.setName("Deepak1"); Session sessionTwo=factory.openSession(); Employee employee1=(Employee)sessionTwo.get(Employee.class, 5); sessionTwo.beginTransaction(); sessionTwo.saveOrUpdate(employee); // it will throw exception //sessionTwo.merge(employee); // it will work sessionTwo.getTransaction().commit(); sessionTwo.close(); } private static void save(SessionFactory factory) { Session sessionOne=factory.openSession(); Employee emp=new Employee(); emp.setName("Abhi"); emp.setSalary(10000); sessionOne.beginTransaction(); try{ sessionOne.save(emp); sessionOne.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); }finally{ sessionOne.close(); } } }
fuente