Ceci est tiré de la section 10.7. Détection automatique de l'état de la documentation de référence Hibernate:
saveOrUpdate () effectue les opérations suivantes:
- si l'objet est déjà persistant dans cette session, ne rien faire
- si un autre objet associé à la session a le même identifiant, lever une exception
- si l'objet n'a pas de propriété d'identifiant, enregistrez-le ()
- si l'identifiant de l'objet a la valeur assignée à un objet nouvellement instancié, save () it
- si l'objet est versionné (par une <version> ou <timestamp>) et que la valeur de la propriété de version est la même valeur affectée à un objet nouvellement instancié, save () it
- sinon mettre à jour () l'objet
et merge () est très différent:
- s'il existe une instance persistante avec le même identifiant actuellement associé à la session, copiez l'état de l'objet donné sur l'instance persistante
- s'il n'y a pas d'instance persistante actuellement associée à la session, essayez de la charger à partir de la base de données ou créez une nouvelle instance persistante
- l'instance persistante est retournée
- l'instance donnée n'est pas associée à la session, elle reste détachée
Vous devez utiliser Merge () si vous essayez de mettre à jour des objets qui étaient à un moment donné détachés de la session, en particulier s'il peut y avoir des instances persistantes de ces objets actuellement associés à la session. Sinon, l'utilisation de SaveOrUpdate () dans ce cas entraînerait une exception.
SaveOrUpdateCopy
n'est pas la même chose queSaveOrUpdate
. Je ne sais pas si l'interlocuteur voulait comparerMerge
le premier ou le second.SaveOrUpdateCopy
est une méthode désormais obsolète qui a effectué une fusion dans NHibernate avant d'Merge
être importée.Si je comprends bien,
merge()
prendra un objet qui ne peut être associé à la session en cours, et copier son état ( la valeur des propriétés, etc.) à un objet qui est associé à la session en cours (avec la même valeur PK / identifiant, de cours).saveOrUpdate()
appellera Save ou Update sur votre session, en fonction de la valeur d'identité d'un objet donné.la source
SaveOrUpdateCopy()
est désormais obsolète depuis NHibernate 3.1.Merge()
devrait être utilisé à la place.la source
SaveOrUpdateCopy
qui est marquéObsolete
, nonSaveOrUpdate
. Il semble y avoir beaucoup de confusion entre ces deux méthodes différentes dans cette question et les réponses ultérieures.** Update()**
: - si vous êtes sûr que la session ne contient pas une instance déjà persistante avec le même identifiant alors utilisez update pour sauvegarder les données en hibernation
** Merge()**
: -si vous voulez enregistrer vos modifications à tout moment sans connaître l'état d'une session, utilisez merge () en hibernation.
la source
J'ai trouvé ce lien qui a fait un très bon travail expliquant ce type d'exception:
Ce qui a fonctionné pour moi est le suivant:
cascade="merge"
SaveOrUpdate
l'objet enfant / dépendant avant de l'affecter à l'objet parent.SaveOrUpdate
l'objet parent.Cependant, cette solution a des limites. c'est-à-dire que vous devez prendre soin de sauvegarder votre enfant / objet dépendant au lieu de laisser hiberner faire cela pour vous.
Si quelqu'un a une meilleure solution, j'aimerais voir.
la source
@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(); } } }
la source