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生成策略来递增,则输出没有差异。
答案 0 :(得分:1)
这是一个简单的逻辑问题。
它不保证标识符值将立即分配给持久性实例
与
不同它保证标识符值不会立即分配给持久化实例
用于数据库的ID生成策略是使用序列。在这种情况下,Hibernate在调用persist()时会询问序列中的下一个ID。如果数据库的ID生成策略是使用自动增量列,则只有在实体插入数据库时,才会在刷新时将ID分配给实体。
答案 1 :(得分:1)
所有信息都在文档中。进行呼叫时,save()
会将实体刷新到数据库。 persist()
实际上只是标记要在即将到来的同花顺中保留的实体。存在差异,使用persist
可以更好地控制实际写入数据库的时间。