什么是Hibernate中的persist()和save()之间的区别?

时间:2011-11-11 17:26:24

标签: hibernate

通过文档,我发现只有一个区别就是save方法生成的对象作为生成的标识符返回,但是persist却没有。这是提供持久化方法的唯一目的。如果是程序员如何帮助它,即使他不打算使用生成的标识符,他可以使用save并忽略返回值。

同样来自What's the advantage of persist() vs save() in Hibernate?的这个主题。我可以从这个线程获得的有意义的语句 persist()还保证如果在事务边界之外调用它不会执行INSERT语句,保存方法但不确定我应该如何尝试它在我的程序中,以便我可以获得实际的差异?

6 个答案:

答案 0 :(得分:14)

我做了一些模拟测试来记录Save()和Persist()之间的区别。

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

对于下面的示例,将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') //这是针对生成的车辆ID:36

insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)

Repeat the same with using persist(entity) and will result the same with new Id ( say 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,名称为“丰田”

         select nextval ('hibernate_sequence')
         insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)

         (ii) Using Persist()  to persist a detached object 

            // Session 1 
            Session session = factory.openSession();
    session.beginTransaction();
    EmployeeVehicle entity = EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
    session.close();

//第2节 //在会话2中,在前一个会话中获得的车辆实体是一个分离的对象,现在我们将尝试保存/保留它 (i)使用persist()来保存分离的对象

            Session session2 = factory.openSession();
    session2.beginTransaction();
            entity.setVehicleName("Toyota");
    session2.persist(entity);
    session2.getTransaction().commit();
    session2.close();

结果:抛出异常:传递给persist的分离实体

因此,最好使用Persist()而不是Save(),因为在处理会话和转换时必须小心使用save。

答案 1 :(得分:5)

  • 返回类型:两个函数都将记录INSERT到数据库中,但返回类型为persist()方法为void,而返回类型为save()的方法是主键id值为由hibernate生成。

  • 标识符:persist()方法不保证标识符值会立即分配给持久化实例,分配可能会在刷新时发生。

  • 事务边界:我们只能在事务内部调用persist()方法,因此它是安全的并且可以处理任何级联对象。 save()方法可以在事务内部或外部调用。

  • 上下文:persist()方法将实体对象添加到持久上下文并跟踪任何进一步的更改。在提交事务时保存任何进一步的更改,如persist。

最后persist()方法优于save()。

examples

答案 2 :(得分:3)

save()返回一个标识符,如果必须执行INSERT来获取标识符,则无论您是在事务内部还是外部,都会立即执行此INSERT。这与使用扩展的会话/持久性上下文的长时间对话不太好。

persist()用于瞬态对象。它使瞬态实例持久化。但是,它不保证标识符值将立即分配给持久性实例,分配可能在刷新时发生。它还保证如果在事务边界之外调用它,它将不会执行INSERT语句。这对于具有扩展会话/持久性上下文的长时间运行会话非常有用。

答案 3 :(得分:3)

<强>留存():

  • 这是一个void方法,不保证标识符值是 在INSERT之后分配给持久性实例。任务可能 在冲洗时发生。
  • 如果从外部交易中调用它,则不会执行 边界。
  • 对于具有扩展会话/持久性上下文的长时间运行会话非常有用。

保存():

  • 执行INSERT后将返回标识符。
  • 即使在交易边界外也会执行。
  • 对长时间对话没用。

答案 4 :(得分:2)

public class TestSave {

public static void main(String[] args) {

    Session session= HibernateUtil.getSessionFactory().openSession();
    Person person= (Person) session.get(Person.class, 1);
    System.out.println(person.getName());
    session.close();

    Session session1= HibernateUtil.getSessionFactory().openSession();
    session1.beginTransaction();

    person.setName("person saved with Persist");
    session1.getTransaction().commit();
    System.out.println(session1.save(person));

    //session1.persist(person);
    session1.flush();

    session1.close();

}
}

保存和保持之间的区别,保存在事务外部执行。执行上面的代码并检查控制台System.out.println(session1.save(person))将返回标识符并再次执行它,它将增加您的标识符。现在,如果您尝试使用以下代码在数据库的Person表中保存另一条记录,并刷新数据库表并检查数据库中的id列。它的值会增加。

public class TestMain {
  public static void main(String[] args) {
    Person person = new Person();
    saveEntity(person);
 }
private static void saveEntity(Person person) {
person.setId(1);
 person.setName("Concretepage1");
 Session session = HibernateUtil.getSessionFactory().openSession();
 session.beginTransaction();
 session.save(person);
 session.getTransaction().commit();
 session.close();
}

如果我们尝试将数据保留在事务边界之外,则会给出异常。

答案 5 :(得分:0)

save()方法通常会在外部事务处理中插入语句

public class HibernateSaveExample {

    public static void main(String[] args) {

        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        Student student = new Student("javabycode.com", new Date(), "USA", "1234569");
        Long studentId = (Long) session.save(student);
        System.out.println(" Identifier : " + studentId);
        System.out.println(" Successfully saved");

        Session session2 = sessionFactory.openSession();
        Transaction trans = session2.beginTransaction();

        Student student2 = new Student("javabycode.com", new Date(), "USA", "1234569");
        Long studentId2 = (Long) session2.save(student2);
        trans.commit();
        System.out.println(" Identifier : " + studentId2);
        System.out.println(" Successfully saved");

        sessionFactory.close();
    }

}

并且persist()方法无法做到。

Hibernate中的save和persist方法之间的另一个区别是:JPA支持persist,而只有Hibernate支持save。

来自教程Difference between save and persist method in Hibernate