save,saveorUpdate和merge方法如何在hibernate中工作?

时间:2015-03-11 14:11:27

标签: java hibernate

我对save,saveOrUpdate和merge感到困惑。以下是我以前检查的测试,现在更加困惑:)。

DESC :我有 Emp Certs 实体。 Emp和Certs使用一对多映射父子关系。我从方法调用 saveEmployee()方法,然后调用 save() saveOrUpdate(),逐步 merge()方法来测试他们的行为

Emp Entity

@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实体

@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(); 
      }
}

案例1:saveOrUpdate()

方法save()和merge()注释。结果如下:

tmp_emp 表格:

enter image description here

tmp_certs

enter image description here

所以从这个和hibernate sqls我可以推断出Emp实体和Certs首先被插入,后来所有3个都被更新了。我认为它有一个初始插入和稍后的更新。

案例2:保存()

方法saveOrUpdate()和merge()注释。结果如下:

tmp_emp

enter image description here

tmp_certs

enter image description here

这是对save方法的调用。两个会话的Emp和Certs对象相同。这次emp对象被认为是2个对象,并且两个员工都被保存到emp表中。但是Certs被视为同样的对象。它们已插入并随后更新(使用新的empId)。 Hibernate SQL也显示相同。 2个用于Emp的插入,2个用于Certs的插入,然后在相同的Certs上更新2个(可以看到empId:112更新了证书)

案例3:合并()

方法save()和saveOrUpdate()注释。结果如下

tmp_emp

enter image description here

tmp_certs

enter image description here

每次使用merge()时,Emp和Certs对象都被视为新对象。因此在Hibernate sql中有2个用于Emp的插入和4个用于Certs的插入。

我经历了这个LINK,但我无法与这些案件联系起来。任何理解这种行为的帮助都将非常感激。

1 个答案:

答案 0 :(得分:0)

我没有读过你的问题,对你要做的事情有点困惑。但是,我会在这里解释一下。

    session.save()对象上的
  1. transient/detached将始终在数据库表中创建一行。
  2. session.saveOrUpdate()将保存transient对象or更新detached对象。  如果会话中存在持久性对象,那么它将抛出一个异常,说明具有该id的对象已经在会话中。
  3. <强>例如

    public void saveSomething(Something one){//here one.id = 33 too
        ..
        Something second = (Something) session.get(Something.class, 33); //get entity of id 33
    
        //try to update one here
        session.saveOrUpdate(one); 
    
        //commit your transaction...  EXCEPTION WILL BE THROWN AS SOMETHING OBJECT WITH 33 ID IS IN THE SESSION ALREADY
    }
    
    1. session.merge()将会话中的值替换为分离对象的值。它不关心你对会话中的实际实体做什么。不会抛出异常。
    2. <强>例如

      public void saveSomething(Something one){
          //here one.id = 33 too
          //one.name ='Abdulla'
      
          ..
          Something second = (Something) session.get(Something.class, 33); //get entity of id 33. 
          //second.name = 'Frank'
          //second.age = 33
          //change name here to Mark
          second.setName('Mark');
          //try to merge one here into the session.
          session.merge(one);     
          //now the session will have values of 'one' in it as they are replaced
          Something third = (Something) session.get(Something.class, 33);
          //now you'll get the following values if you try to get the 
          //value as you have overwritten what is already present in the session. 
          //You'll not get Mark as they are replaced by the merge operation.
          //third.id = 33
          //third.age = 33    
          //third.name ='Abdulla' 
      }