在Hibernate中persist()vs save()的优点是什么?

问题

谁能告诉我什么是Hibernate的优势?persist()vssave()


#1 热门回答(132 赞)

Fromthis forum post

persist()定义明确。它使瞬态实例持久化。但是,它不保证标识符值将立即分配给持久性实例,分配可能在刷新时发生。规范没有说明,这是我用persist()的问题。 persist()还保证如果在事务边界之外调用它,它将不会执行INSERT语句。这在使用扩展的会话/持久性上下文的长时间运行的对话中非常有用。需要像persist()这样的方法。 save()不保证相同,它返回一个标识符,如果必须执行INSERT来获取标识符(例如"identity"生成器,而不是"sequence"),无论你是否在里面,这个INSERT都会立即发生或在交易之外。这与使用扩展的会话/持久性上下文的长时间对话不太好。


#2 热门回答(45 赞)

我对save()vs persist()进行了很好的研究,包括在我的本地机器上多次运行它。所有以前的解释都令人困惑,并且不正确。经过深入研究后,我已经比较了下面的save()和persist()。

Save()

  • 保存后返回生成的Id。它的Serializable返回类型。
  • 立即将值保存到DB并跟踪实体直到会话结束(我试图在事务之外更改实体值,当会话提交时它没有显示任何效果)
  • 不将更改保存到事务外部的数据库中。
  • 将生成的id分配给你持久存储的实体
  • 分离对象的Session.save()将在表中创建一个新行。
    Persist()-保存后不返回生成的Id。它的返回类型。
  • 立即将值保存到DB并跟踪实体直到会话结束。(我试图在事务之外更改实体值,当会话提交时它没有显示任何效果)
  • 不将更改保存到事务外部的数据库中。
  • 将生成的id分配给你持久存储的实体
  • 分离对象的session.persist()将抛出PersistentObjectException,因为它是不允许的。

所有这些都在Hibernate v4.0.1上进行了试验/测试。


#3 热门回答(22 赞)

我做了一些模拟测试来记录save()persist()之间的差异。

听起来这两种方法在处理Transient Entity时表现相同,但在处理Detached Entity时有所不同。

对于下面的示例,将EmployeeVehicle作为实体,PK为asvehicleId,这是一个生成的值,其中一个属性为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,本田)相同;

示例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不是生成的值,则会导致异常声明密钥被违反。