EntityManager的merge()方法相当于hibernate中session的saveOrUpdate()方法;
用于实体的插入和更新操作;
1.临时状态的实体对象
创建一个新对象;
将临时对象的属性复制到新对象;
持久化新对象;
执行insert插入到数据库;
代码:
//merge的第一种情况:临时对象
@Test
public void testMerge1(){
Emp emp=new Emp();
emp.setBirthday(new Date());
emp.setName("郭将军");
emp.setSalary(200);
Emp emp2=manager.merge(emp);
System.out.println("临时对象emp的id:"+emp.getId());
System.out.println("实际插入的对象emp2的id:"+emp2.getId());
}
结果:
Hibernate:
insert
into
tb_emp
(birthday, name, salary)
values
(?, ?, ?)
临时对象emp的id:null
实际插入的对象emp2的id:26
2.游离对象
游离对象说白了就是有id的临时对象;
查看缓存中是否存在id相同的持久化对象;
如果不存在,就查看数据库,中是否有id相同的记录;
1)缓存中有id相同的持久化对象
将游离对象的属性拷贝到id对应的持久化对象;
在数据库中执行update操作;
2)缓存中没有id相同的持久化对象;但数据库中有相同id的记录
执行查询语句用该id为条件,获取一个持久化对象;
将游离对象的属性拷贝到持久化对象;
执行update操作;
3)数据库和缓存中都没有游离对象id相同的记录
和临时对象一样的步骤;
注意:实际插入对象的id并不是该游离对象的id;
代码:
//merge的第二种情况:游离对象;数据库和缓存中都没有id相同的
@Test
public void testMerge2(){
Emp emp=new Emp();
emp.setBirthday(new Date());
emp.setName("王司徒");
emp.setSalary(200);
emp.setId(5);
Emp emp2=manager.merge(emp);
System.out.println("游离对象emp的id:"+emp.getId());
System.out.println("实际插入的对象emp2的id:"+emp2.getId());
}
结果:
Hibernate:
select
emp0_.id as id1_0_0_,
emp0_.birthday as birthday2_0_0_,
emp0_.name as name3_0_0_,
emp0_.salary as salary4_0_0_
from
tb_emp emp0_
where
emp0_.id=?
Hibernate:
insert
into
tb_emp
(birthday, name, salary)
values
(?, ?, ?)
游离对象emp的id:5
实际插入的对象emp2的id:27
3.与hibernate的不同
hibernate的session无法同时与两个id相同的对象相关联;
也就是说:find和merge同时使用时如果id相同可能会报错;
而EntityManager是复制操作,可以这样用;