简体   繁体   中英

Hibernate persist() vs save() method

The hibernate document says:

persist():

persist() makes a transient instance persistent. 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. This is useful in long-running conversations with an extended Session/persistence context.

save():

save() does guarantee to return an identifier. 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. 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:

@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() :

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:

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

Finally, when I use the transaction then the data is stored in the DB table.

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.

Now I modified my entity class Id generation strategy to increment as follows:

@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. 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. So there is no difference in output if I use Id generation strategy to increment.

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. In that case, Hibernate asks the sequence for the next ID when calling persist(). 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.

All the information is in the documentation. save() flushes the entity to the database when you make the call. persist() actually just marks the entity to be persisted in the upcoming flush. There is a difference and with persist you have more control on when the actual write to the database takes place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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