I was bit confused with save, saveOrUpdate and merge. Below is the test I used to check and got even more confused now :).
DESC: I have Emp and Certs entities. The Emp and Certs have a parent child relationship mapped using One-to-Many. I make a call to saveEmployee() method from Main method and call save(), saveOrUpdate() and merge() methods one by one to test their behaviors.
Emp EntityCode:
@Entity
@Table(name = "tmp_emp")
public class Emp {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "EMP_ID")
private Long empId;
@Column(name = "FIRST_NAME")
String firstName;
@Column(name = "LAST_NAME")
String lastName;
@Column(name= "SALARY")
Integer salary;
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "emp")
Set<Certs> certSet;
// getters-setters
Certs EntityCode:
@Entity
@Table(name = "tmp_certs")
public class Certs {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "EMPCERT_ID")
private Long empCertId;
@Column(name = "CERT_NAME")
String certName;
@ManyToOne(targetEntity = Emp.class)
@JoinColumn(name = "EMP_ID")
private Emp emp;
//getters-setters
Main methodCode:
public static void main(String[] args) {
AnnotationConfiguration config = new AnnotationConfiguration();
config.configure("hibernate-config.xml").addAnnotatedClass(Emp.class);
config.configure("hibernate-config.xml").addAnnotatedClass(Certs.class);
SessionFactory factory = config.buildSessionFactory();
// Creating 1st Cert object, set cert name
Certs cert1 = new Certs();
cert1.setCertName("OCJP");
// Creating 2nd Cert object, set cert name
Certs cert2 = new Certs();
cert2.setCertName("PMP");
// Creating a Hashset to store Certs.
Set<Certs> certsSet = new HashSet<Certs>();
// Adding certs to Hashset
certsSet.add(cert1);
certsSet.add(cert2);
// Creation of Emp Object.
Emp emp = new Emp();
// First call to saveEmployee method.
saveEmployee(emp, "Rick", "Ved", 3000, factory, certsSet);
// Second call to saveEmployee method with same emp and certs hashset.
saveEmployee(emp, "George", "Tank", 5000, factory, certsSet);
}
Below is the
saveEmployee() method theat is being called Main. In SaveEmployee method I call
saveOrUpdate(),
save() and
merge() methods one by one.
Code:
private static void saveEmployee(Emp emp,String fname,String lname,Integer sal, SessionFactory factory, Set<Certs> certsSet) {
Session session = factory.openSession();
Transaction tx =null;
try{
tx = session.beginTransaction();
// Setting Firstname, Lastname and Salary of emp object.
emp.setFirstName(fname);
emp.setLastName(lname);
emp.setSalary(sal);
// Iterate Cert Hashset and set empId to Cert Objects.
Iterator<Certs> itr = certsSet.iterator();
while(itr.hasNext()){
Certs c = itr.next(); c.setEmp(emp);
}
emp.setCertSet(certsSet);
session.saveOrUpdate(emp); // CASE 1
// session.save(emp); // CASE 2
// session.merge(emp); //CASE 3
session.flush();
tx.commit();
}catch(HibernateException e){
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
// Close the session.
session.close();
}
}
Case 1: saveOrUpdate() Methods save() and merge() commented. Results are as below:
tmp_emp table:
tmp_certs table
So from this and hibernate sqls I can infer that the Emp entity and Certs got inserted first and later all 3 got updated. But as am passing same Emp and Certs objects 2 different sessions. I suppose its fine with an initial insert and later an update.
Case 2: save()Methods saveOrUpdate() and merge() commented. Results are as below:
tmp_emp table
tmp_certs table
Here it's a call to save method. Again same Emp and Certs objects for both sessions. This time emp object was considered as 2 objects and both employees got saved to emp table. But again Certs were treated as same objects. They got inserted and later got updated(with new empId). Hibernate SQL too shows the same. 2 Inserts for Emp, 2 Inserts for Certs then 2 update on same Certs ( can see empId: 112 updated on certs)
Case 3: merge()Methods save() and saveOrUpdate() commented.Results are as below
tmp_emp table
tmp_certs table
Here using merge() each time Emp as well as Certs objects are getting treated as new objects. So there are 2 Inserts for Emp and 4 Inserts for Certs in Hibernate sql.
I went through this
http://stackoverflow.com/questions/7475363/differences-among-save-update-saveorupdate-merge-methods-in-session but am not able to relate to these cases.
Any help in understanding this behavior would be greatly appreciated.