Card 03/ 07

GotchaDifficulty: Advanced1 min

persist() Doesn't Always Wait for flush()

"The INSERT runs on flush or commit" is the usual rule, and it's true for one of these two entities and false for the other — with no difference in the code that calls persist().

java
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;   // on IdentityThing

@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
Long id;   // on SequenceThing
text
IDENTITY: statements right after persist(), before flush: 1
IDENTITY: statements after flush(): 1

SEQUENCE: statements right after persist(), before flush: 1
SEQUENCE: statements after flush(): 2
run in a container, real Hibernate statistics — identical calling code, different generation strategy

With GenerationType.IDENTITY, the database itself assigns the id — an auto-increment column — and there is no way to know what it is without actually running the INSERT. So persist() runs it immediately; flush() finds nothing left to do. With GenerationType.SEQUENCE, Hibernate can fetch the next id from a separate sequence up front — that's the one statement before flush — and defer the row's actual INSERT the way the general rule describes.