简体   繁体   English

Hibernatepersist()vs save()方法

[英]Hibernate persist() vs save() method

The hibernate document says: 休眠文件说:

persist(): 坚持():

persist() makes a transient instance persistent. persist()使瞬态实例持久化。 However, it does not guarantee that the identifier value will be assigned to the persistent instance immediately, the assignment might happen at flush time. 但是,它不能保证将标识符值立即分配给持久实例,分配可能在刷新时发生。 persist() also guarantees that it will not execute an INSERT statement if it is called outside of transaction boundaries. persist()还保证如果在事务边界之外调用它,则不会执行INSERT语句。 This is useful in long-running conversations with an extended Session/persistence context. 这在具有扩展会话/持久性上下文的长时间对话中很有用。

save(): 救():

save() does guarantee to return an identifier. save()保证返回标识符。 If an INSERT has to be executed to get the identifier ( eg "identity" generator, not "sequence"), this INSERT happens immediately, no matter if you are inside or outside of a transaction. 如果必须执行INSERT来获取标识符(例如,“身份”生成器,而不是“序列”),则无论您是在事务内部还是外部,此INSERT都会立即发生。 This is problematic in a long-running conversation with an extended Session/persistence context. 在具有扩展的会话/持久性上下文的长时间对话中,这是有问题的。

So I am trying with a small example on how this works. 因此,我正在尝试一个有关其工作原理的小例子。 I created an entity called DomesticCat: 我创建了一个名为DomesticCat的实体:

@Entity
public class DomesticCat {

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

and a small program to test this, once using save() and another time with persist() : 以及一个小程序对此进行测试,一次使用save() ,另一次使用persist()

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

For this program, hibernate generated same queries for save & persist, in this case it is: 对于此程序,hibernate生成了相同的保存和持久化查询,在这种情况下为:

select hibernate_sequence.nextval from dual

Now I added an extra line to my code saying: 现在,我在代码中增加了一行:

session.flush();

Now hibernate generated insert query for both cases ie save & persist: 现在,休眠生成两种情况下的插入查询,即保存并持续:

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

Also when I do session.flush() , the id is getting assigned to my cat object when I use save() and also for persist() 同样当我执行session.flush() ,当我使用save()以及persist()时,也将id分配给我的cat对象

Finally, when I use the transaction then the data is stored in the DB table. 最后,当我使用事务时,数据将存储在DB表中。

So using this example I can see only single difference between persist vs save, that is save returns the identifier where as persist will not. 因此,使用此示例,我只能看到持久性与保存之间的唯一区别,即保存返回标识符,而持久性则不会。

Then what exactly the document says, can someone please help me with some examples? 那么,文件确切说明了什么,有人可以帮我提供一些例子吗?

Update: 更新:

I am using Oracle as my database. 我正在使用Oracle作为数据库。

Now I modified my entity class Id generation strategy to increment as follows: 现在,我将实体类ID生成策略修改为如下递增:

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

But even then I can see that calling session.persist() is hitting the DB to get the Id value. 但是即使那样,我仍然可以看到调用session.persist()正在击中数据库以获取Id值。 Here is my program and its output: 这是我的程序及其输出:

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());
}

Output: 输出:

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

As per the output hibernate is hitting the DB to get the ID before I call session.flush() and the case is same for session.save() also. 根据输出,休眠状态是在我调用session.flush()之前命中数据库以获取ID,session.save()的情况也相同。 So there is no difference in output if I use Id generation strategy to increment. 因此,如果我使用ID生成策略递增,则输出不会有差异。

It's a simple logic problem. 这是一个简单的逻辑问题。

it does not guarantee that the identifier value will be assigned to the persistent instance immediately 它不能保证将标识符值立即分配给持久实例

is not the same thing as 和...不一样

it guarantees that the identifier value will not be assigned to the persistent instance immediately 它保证不会立即将标识符值分配给持久实例

The ID generation strategy used for your database is to use a sequence. 用于数据库的ID生成策略是使用序列。 In that case, Hibernate asks the sequence for the next ID when calling persist(). 在这种情况下,Hibernate在调用persist()时向序列询问下一个ID。 If the ID generation strategy for your database was to use an auto-increment column, the ID would only be assigned to the entity only when the entity is inserted to the database, at flush time. 如果数据库的ID生成策略是使用自动增量列,则仅在刷新时将实体插入数据库时​​,才将ID分配给实体。

All the information is in the documentation. 所有信息都在文档中。 save() flushes the entity to the database when you make the call. 调用时, save()将实体刷新到数据库。 persist() actually just marks the entity to be persisted in the upcoming flush. persist()实际上只是将实体persist()在即将到来的刷新中。 There is a difference and with persist you have more control on when the actual write to the database takes place. 这是有区别的,并且通过persist您可以更好地控制何时实际写入数据库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM