Java Hibernate persist()vs save()方法
报告说: persist(): persist()使临时实例持久化。但是,它不能保证将标识符值分配给 如果是持久实例,则分配可能会在刷新时发生 时间persist()还保证它不会执行插入 语句(如果在事务边界之外调用)。这是 在与扩展用户的长时间对话中非常有用 会话/持久性上下文 save(): save()不保证返回标识符。如果必须执行插入以获取标识符(例如“标识”生成器,而不是 “序列”),无论您是否 在交易的内部或外部。这在某种程度上是有问题的 具有扩展会话/持久性的长时间运行对话 上下文 所以我试着用一个小例子来说明它是如何工作的。我创建了一个名为DomesticCat的实体:Java Hibernate persist()vs save()方法,java,hibernate,Java,Hibernate,报告说: persist(): persist()使临时实例持久化。但是,它不能保证将标识符值分配给 如果是持久实例,则分配可能会在刷新时发生 时间persist()还保证它不会执行插入 语句(如果在事务边界之外调用)。这是 在与扩展用户的长时间对话中非常有用 会话/持久性上下文 save(): save()不保证返回标识符。如果必须执行插入以获取标识符(例如“标识”生成器,而不是 “序列”),无论您是否 在交易的内部或外部。这在某种程度上是有问题的 具有扩展会话/持久性的长时间运行对话 上下文
@Entity
public class DomesticCat {
@Id
@GeneratedValue
private long id;
private String name;
}
还有一个小程序来测试这一点,一次使用save()
,另一次使用persist()
:
对于该程序,hibernate为保存和持久化生成了相同的查询,在本例中为:
select hibernate_sequence.nextval from dual
现在,我在我的代码中添加了一行额外的代码:
session.flush();
现在hibernate为这两种情况生成了插入查询,即保存和持久化:
insert into CAT (name, id) values (?, ?)
另外,当我执行session.flush()
时,当我使用save()和persist()时,id
被分配给我的cat
对象
最后,当我使用事务时,数据存储在DB表中
因此,使用这个示例,我可以看到persist和save之间只有一个区别,即save返回标识符,而as 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
根据输出,在我调用session.flush()之前,hibernate正在点击数据库获取ID,session.save()的情况也一样。所以,如果我使用Id生成策略来增加,输出没有区别。这是一个简单的逻辑问题 它不能保证标识符值将立即分配给持久实例 这和 它保证不会立即将标识符值分配给持久实例
数据库使用的ID生成策略是使用序列。在这种情况下,Hibernate在调用persist()时向序列询问下一个ID。如果数据库的ID生成策略是使用自动增量列,则仅当实体在刷新时插入数据库时,才会将ID分配给实体。所有信息都在文档中
save()
在调用时将实体刷新到数据库中persist()
实际上只是在即将到来的刷新中标记要持久化的实体。这是有区别的,使用persist
可以更好地控制对数据库的实际写入时间。关键在于这在长时间运行的对话中非常有用,其中persist
比save
更可取(插入许多对象)。感谢您的回答。现在,我将Id生成策略设置为增量,并且使用save和persist没有任何区别。我已经更新了我的问题,详细说明了我的尝试。你能检查一下吗?这不是我的意思。我的意思是在数据库中使用自动递增列。Oracle没有这个功能。比如说MySQL,谢谢heikkim,你能给我一个小例子,让我看看两者的区别吗。
before id=0
Hibernate: select max(id) from CAT
after id=1
Hibernate: insert into CAT (name, id) values(?, ?)
after flush id=1