В чем разница между сессией.Слияние и сеанс.SaveOrUpdate?
Я иногда замечаю, что с моими родительскими/дочерними объектами или отношениями "многие ко многим" мне нужно позвонить либо SaveOrUpdate
или Merge
. Обычно, когда мне нужно позвонить SaveOrUpdate
, исключение я получаю на вызов Merge
имеет отношение к переходным объектам, которые не сохраняются в первую очередь.
Пожалуйста, объясните разницу между двумя.
7 ответов:
Это из раздела 10.7. Автоматическое определение состояния из справочной документации Hibernate:
saveOrUpdate() делает следующее:
- если объект уже сохранен в этом сеансе, ничего не делайте
- если другой объект, связанный с сеансом имеет тот же идентификатор, бросьте исключение
- если объект не имеет свойства идентификатора, сохраните () it
- если объект идентификатор имеет значение, присвоенное недавно инстанцировать объект, сохранить() это
- если объект версионный (по
или ), и значение свойства version-это то же значение, которое было присвоено новому инстанцировать объект, сохранить() это - в противном случае обновить () объект
и merge() очень отличается:
- если в настоящее время существует постоянный экземпляр с тем же идентификатором связанные с сеанс, копирование состояния данного объекта на постоянный экземпляр
- если в настоящее время нет постоянного экземпляра, связанного с сеанс, попробуйте загрузить его из базы данных или создать новый постоянный экземпляр
- постоянный экземпляр возвращается
- данный экземпляр не становится связанным с сеансом, он остается отстраненным
вы должны использовать Merge (), если вы пытаетесь обновить объекты, которые были в какой-то момент отделены от сеанса, особенно если могут существовать постоянные экземпляры тех объектов, которые в настоящее время связаны с сеансом. В противном случае использование SaveOrUpdate() в этом случае приведет к исключению.
Как я понимаю,
merge()
возьмет объект, который не может быть связан с текущим сеансом, и скопирует его состояние (значения свойств и т. д.) к объекту, который - это связанный с текущей сессией (с тем же значением/идентификатором PK, конечно).
saveOrUpdate()
будем называть сохранить или обновление на вашем сеансе, на основе значения идентификатора данного объекта.
нашел этой ссылка, которая сделала довольно хорошую работу, объясняя этот тип исключения:
что сработало для меня следующее:
- в отображении Myclass.hbm.xml-файл, set
cascade="merge"
SaveOrUpdate
дочерний / зависимый объект сначала перед назначением его родительскому объекту.SaveOrUpdate
родительский объект.однако, это решение имеет ограничения. то есть, вы должны заботиться о сохранении вашего дочерний / зависимый объект вместо того, чтобы позволить hibernate делать это за вас.
Если у кого есть лучшее решение, я хотел бы видеть.
новый идентификатор пользователя, поэтому я не могу комментировать или голосовать за сообщение Quoc Truong. Однако я также думаю, что ссылка довольно полезна, как было указано ранее.
http://www.roseindia.net/hibernate/hibernate4/org_hibernate_nonuniqueobjectexception.shtml
** Update()**
:- Если вы уверены, что сеанс не содержит уже постоянный экземпляр с тем же идентификатором, то используйте update для сохранения данных в hibernate
** Merge()**
:-Если вы хотите сохранить свои изменения в любое время, не зная о состоянии сеанса, то используйте merge() в hibernate.
@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(); } } }