【发布时间】:2015-05-13 09:06:21
【问题描述】:
我对保存、saveOrUpdate 和合并有点困惑。以下是我曾经检查过的测试,现在变得更加困惑:)。
DESC:我有 Emp 和 Certs 实体。 Emp 和 Certs 具有使用一对多映射的父子关系。我从 Main 方法调用 saveEmployee() 方法并调用 save()、saveOrUpdate() 和merge() 方法一一测试其行为
Emp 实体
@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
证书实体
@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
主要方法
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);
}
下面是 saveEmployee 方法。我已经一一使用了saveOrUpdate()、save()和merge()方法。
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();
}
}
案例一:saveOrUpdate()
方法 save() 和 merge() 已注释。结果如下:
tmp_emp 表:
tmp_certs 表
因此,从这个和休眠 sqls 中,我可以推断出 Emp 实体和 Certs 是首先插入的,然后所有 3 个都被更新。我想它可以通过初始插入然后更新。
案例2:save()
方法 saveOrUpdate() 和 merge() 已注释。结果如下:
tmp_emp 表
tmp_certs 表
这里调用了 save 方法。两个会话再次使用相同的 Emp 和 Certs 对象。这次 emp 对象被视为 2 个对象,两个员工都保存到 emp 表中。但是证书再次被视为相同的对象。他们被插入,后来被更新(使用新的 empId)。 Hibernate SQL 也显示相同。 2 次插入 Emp,2 次插入证书,然后 2 次更新相同的证书(可以看到 empId: 112 在证书上更新)
案例 3:merge()
方法save()和saveOrUpdate()注释。结果如下
tmp_emp 表
tmp_certs 表
这里每次将 Emp 和 Certs 对象都视为新对象时使用 merge()。所以在 Hibernate sql 中有 2 个用于 Emp 的插入和 4 个用于 Certs 的插入。
我经历了这个LINK,但无法与这些案例相关联。对于理解这种行为的任何帮助将不胜感激。
【问题讨论】: