我做了一些模拟测试来记录save()和persist()之间的区别。
听起来这两种方法在处理瞬态实体时表现相同,但在处理分离实体时表现不同。
对于以下示例,将 EmployeeVehicle 作为一个实体,PK 为 vehicleId,这是一个生成的值,vehicleName 作为其属性之一。
示例 1:处理瞬态对象
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();
结果:
select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)
注意当你得到一个已经持久化的对象并保存它时结果是一样的
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity); -------> **instead of session.update(entity);**
// session.persist(entity);
使用 persist(entity) 重复相同的操作,结果与新的 Id 相同(比如 37,honda);
示例 2:处理分离的对象
// Session 1
// Get the previously saved Vehicle Entity
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();
// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it
// (i) Using Save() to persist a detached object
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();
结果:您可能期望在上一个会话中获得的具有 id : 36 的车辆已更新为名称为 "Toyota" 。但是发生的情况是,一个新实体被保存在数据库中,为生成的新 ID 和名称为“Toyota”
select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)
使用persist来持久化分离的实体
// (ii) Using Persist() to persist a detached
// Session 1
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();
// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();
结果:
Exception being thrown : detached entity passed to persist
因此,使用 Persist() 而不是 Save() 总是更好,因为在处理 Transient 对象时必须小心使用 save。
重要提示:在上面的例子中,车辆实体的pk是一个生成的值,所以当使用save()来持久化一个分离的实体时,hibernate会生成一个新的id来持久化。但是,如果此 pk 不是生成的值,则会导致异常声明违反密钥。