我对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 表格:
tmp_certs 表
所以从这个和hibernate sqls我可以推断出Emp实体和Certs首先被插入,后来所有3个都被更新了。我认为它有一个初始插入和稍后的更新。
案例2:保存()
方法saveOrUpdate()和merge()注释。结果如下:
tmp_emp 表
tmp_certs 表
这是对save方法的调用。两个会话的Emp和Certs对象相同。这次emp对象被认为是2个对象,并且两个员工都被保存到emp表中。但是Certs被视为同样的对象。它们已插入并随后更新(使用新的empId)。 Hibernate SQL也显示相同。 2个用于Emp的插入,2个用于Certs的插入,然后在相同的Certs上更新2个(可以看到empId:112更新了证书)
案例3:合并()
方法save()和saveOrUpdate()注释。结果如下
tmp_emp 表
tmp_certs 表
每次使用merge()时,Emp和Certs对象都被视为新对象。因此在Hibernate sql中有2个用于Emp的插入和4个用于Certs的插入。
我经历了这个LINK,但我无法与这些案件联系起来。任何理解这种行为的帮助都将非常感激。
答案 0 :(得分:0)
我没有读过你的问题,对你要做的事情有点困惑。但是,我会在这里解释一下。
session.save()
对象上的transient/detached
将始终在数据库表中创建一行。session.saveOrUpdate()
将保存transient
对象or
更新detached
对象。
如果会话中存在持久性对象,那么它将抛出一个异常,说明具有该id的对象已经在会话中。 <强>例如强>
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
}
<强>例如强>
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'
}