Hibernate persist()vs save()方法

时间:2014-09-16 07:04:10

标签: java hibernate

hibernate document说:

坚持():

  

persist()使瞬态实例持久化。但是,它不保证将标识符值分配给   立即执行持久化实例,分配可能发生在flush   时间。 persist()还保证它不会执行INSERT   声明是否在事务边界之外调用。这是   在与扩展的长时间对话中很有用   会话/持久化上下文。

保存():

  

save()确保返回标识符。如果必须执行INSERT以获取标识符(例如"身份"生成器,则不是   "序列"),无论你是谁,这个INSERT都会立即发生   交易内部或外部。这在一个问题上是有问题的   与长时间会话/持久性的长时间对话   上下文。

所以我正在尝试一个关于它是如何工作的小例子。我创建了一个名为DomesticCat的实体:

@Entity
public class DomesticCat {

    @Id
    @GeneratedValue
    private long id;
    private String name;
}

和一个小程序来测试这个,一次使用save(),另一次使用persist()

private static void saveData() {
    Session session = getSession();
    DomesticCat cat = new DomesticCat();
    cat.setName("My Cat");
    //session.save(cat);
    session.persist(cat);
}

对于这个程序,hibernate为save&生成了相同的查询。坚持,在这种情况下它是:

select hibernate_sequence.nextval from dual

现在我在代码中添加了一行:

session.flush();

现在,hibernate为这两种情况生成了插入查询,即save&坚持:

insert into CAT (name, id) values (?, ?)

当我执行session.flush()时,id在我使用save()时被分配给我的cat对象,并且还用于persist()

最后,当我使用事务时,数据存储在数据库表中。

所以使用这个例子我只能看到persist vs save之间的区别,即save会返回标识符,而persist则不会。

那么文件究竟是什么意思,有人可以帮我一些例子吗?

更新

我使用Oracle作为我的数据库。

现在我修改了我的实体类ID生成策略,增量如下:

@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment") 
private long id;

但即便如此,我也可以看到调用session.persist()正在命中数据库以获取Id值。这是我的程序及其输出:

private static void saveData() {
    Session session = getSession();
    DomesticCat cat = new DomesticCat();
    cat.setName("My Cat");
    System.out.println("before id="+cat.getId());
    session.persist(cat);
    System.out.println("after id="+cat.getId());
    session.flush();
    System.out.println("after flush id="+cat.getId());
}

输出:

before id=0
Hibernate: select max(id) from CAT
after id=1
Hibernate: insert into CAT (name, id) values(?, ?)
after flush id=1

根据输出hibernate在调用session.flush()之前命中DB来获取ID,session.save()的情况也是如此。因此,如果我使用Id生成策略来递增,则输出没有差异。

2 个答案:

答案 0 :(得分:1)

这是一个简单的逻辑问题。

  

它不保证标识符值将立即分配给持久性实例

不同
  

它保证标识符值不会立即分配给持久化实例

用于数据库的ID生成策略是使用序列。在这种情况下,Hibernate在调用persist()时会询问序列中的下一个ID。如果数据库的ID生成策略是使用自动增量列,则只有在实体插入数据库时​​,才会在刷新时将ID分配给实体。

答案 1 :(得分:1)

所有信息都在文档中。进行呼叫时,save()会将实体刷新到数据库。 persist()实际上只是标记要在即将到来的同花顺中保留的实体。存在差异,使用persist可以更好地控制实际写入数据库的时间。