1
0

Add hibernate-demo: get() vs load(), merge() vs refresh(), inserting objects (Hibernate 7.4.1.Final + Spring Boot 4.1.0)

Adds a JUnit test suite (GetVsGetReferenceTest, MergeRefreshTest, OptimisticLockTest,
IdentityBatchTest, SequenceBatchTest, AllocationSizeSweepTest, BatchSizeSweepTest) so every
surprising behavior described in the three companion posts has a reproducible test, alongside
the original CommandLineRunner scenarios. Rewrites all three doc chapters and the README around
the new experiments: the get()/getReference() same-session matrix, the merge()/refresh()
experiments (including exactly when OptimisticLockException surfaces and a corrected LAZY-plus-
cascade merge() result), and two new sweeps (allocationSize, batch_size) for batch inserts.
This commit is contained in:
2026-08-26 17:26:04 +00:00
commit 7b06d653e4
43 changed files with 3053 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
allocationSize=50, batch_size=1, 30 rows -> prepareStatementCount=32
allocationSize=50, batch_size=10, 30 rows -> prepareStatementCount=2
allocationSize=50, batch_size=25, 30 rows -> prepareStatementCount=2
allocationSize=50, batch_size=50, 30 rows -> prepareStatementCount=2
allocationSize=50, batch_size=25, 30 rows -> prepareStatementCount=3
allocationSize=25, batch_size=25, 30 rows -> prepareStatementCount=4
allocationSize=10, batch_size=25, 30 rows -> prepareStatementCount=5
allocationSize=1, batch_size=25, 30 rows -> prepareStatementCount=31

View File

@@ -0,0 +1,70 @@
Hibernate: select next value for book_seq
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Effective Java]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [1]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
Hibernate: select next value for book_seq
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Domain-Driven Design]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [2]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [2]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Outlives Session]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [3]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Matrix: getReference/getReference]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [4]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Matrix: get/getReference]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [5]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [5]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Matrix: get/get]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [6]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [6]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Proxy Identity]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [7]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [7]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [7]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [999111222]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [999333444]
getReference() on a missing id, once accessed, threw: jakarta.persistence.EntityNotFoundException: No row with the given identifier exists for entity [com.ankurm.hibernatedemo.model.Book with id '999333444']
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Matrix: getReference/get]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [8]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [8]
get() after getReference(): prepareStatementCount for this call = 1, returned class = com.ankurm.hibernatedemo.model.Book$HibernateProxy

View File

@@ -0,0 +1,46 @@
Hibernate: create global temporary table HTE_book(rn_ integer not null, id bigint, version bigint, author varchar(255), title varchar(255), primary key (rn_)) transactional
Hibernate: create global temporary table HTE_widget_sequence(rn_ integer not null, id bigint, name varchar(255), primary key (rn_)) transactional
Hibernate: create table book (id bigint not null, author varchar(255), title varchar(255), version bigint not null, primary key (id))
Hibernate: create table widget_identity (id bigint generated by default as identity, name varchar(255), primary key (id))
Hibernate: create table widget_sequence (id bigint not null, name varchar(255), primary key (id))
Hibernate: create sequence book_seq start with 1 increment by 50
Hibernate: create sequence widget_seq start with 1 increment by 25
Hibernate: select next value for book_seq
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,title,version,id) values (?,?,?,?)
binding parameter (1:VARCHAR) <- [Joshua Bloch]
binding parameter (2:VARCHAR) <- [Effective Java]
binding parameter (3:BIGINT) <- [0]
binding parameter (4:BIGINT) <- [1]
SEED: inserted Book id=1
--- Step 1: session.get() on an existing id ---
about to call session.get(Book.class, 1)
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
get() returned: Book{id=1, title=Effective Java, author=Joshua Bloch, version=0}
--- Step 2: session.get() on a missing id ---
about to call session.get(Book.class, 999001)
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [999001]
get() returned: null (no exception thrown)
--- Step 3: session.getReference() on an existing id ---
getReference() returned proxy of class com.ankurm.hibernatedemo.model.Book$HibernateProxy -- no SELECT above this line
now calling proxy.getTitle() ...
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
getTitle() returned 'Effective Java' -- the SELECT for this ran just above this line
--- Step 4: session.getReference() on a missing id ---
getReference() returned a proxy for a row that does not exist -- no exception yet: com.ankurm.hibernatedemo.model.Book$HibernateProxy
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [999001]
accessing the proxy threw jakarta.persistence.EntityNotFoundException: No row with the given identifier exists for entity [com.ankurm.hibernatedemo.model.Book with id '999001']
--- Step 5: proxy accessed after its session is closed ---
session closed. proxy in hand: com.ankurm.hibernatedemo.model.Book$HibernateProxy
accessing the proxy after close threw org.hibernate.LazyInitializationException: Could not initialize proxy [com.ankurm.hibernatedemo.model.Book#1] - no session
--- Step 6: proxy identity vs a real loaded instance ---
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
real.getClass() = com.ankurm.hibernatedemo.model.Book
proxy.getClass() = com.ankurm.hibernatedemo.model.Book$HibernateProxy
proxy instanceof Book.class: true
real.getClass() == proxy.getClass(): false
real.equals(proxy) before proxy access: false

View File

@@ -0,0 +1,71 @@
Hibernate: create global temporary table HTE_book(rn_ integer not null, id bigint, version bigint, author varchar(255), title varchar(255), primary key (rn_)) transactional
Hibernate: create global temporary table HTE_widget_sequence(rn_ integer not null, id bigint, name varchar(255), primary key (rn_)) transactional
Hibernate: create table book (id bigint not null, author varchar(255), title varchar(255), version bigint not null, primary key (id))
Hibernate: create table widget_identity (id bigint generated by default as identity, name varchar(255), primary key (id))
Hibernate: create table widget_sequence (id bigint not null, name varchar(255), primary key (id))
Hibernate: create sequence book_seq start with 1 increment by 50
Hibernate: create sequence widget_seq start with 1 increment by 25
--- inserting 30 WidgetIdentity rows (GenerationType.IDENTITY) ---
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-1]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-2]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-3]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-4]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-5]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-6]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-7]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-8]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-9]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-10]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-11]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-12]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-13]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-14]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-15]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-16]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-17]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-18]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-19]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-20]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-21]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-22]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-23]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-24]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-25]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-26]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-27]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-28]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-29]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetIdentity */insert into widget_identity (name,id) values (?,default)
binding parameter (1:VARCHAR) <- [identity-30]
entityInsertCount = 30
prepareStatementCount = 30
(with IDENTITY, expect prepareStatementCount to land close to entityInsertCount -- each insert has to go to the database immediately to hand back the generated key, so there is nothing left for hibernate.jdbc.batch_size to batch)

View File

@@ -0,0 +1,104 @@
Hibernate: create global temporary table HTE_book(rn_ integer not null, id bigint, version bigint, author varchar(255), title varchar(255), primary key (rn_)) transactional
Hibernate: create global temporary table HTE_widget_sequence(rn_ integer not null, id bigint, name varchar(255), primary key (rn_)) transactional
Hibernate: create table book (id bigint not null, author varchar(255), title varchar(255), version bigint not null, primary key (id))
Hibernate: create table widget_identity (id bigint generated by default as identity, name varchar(255), primary key (id))
Hibernate: create table widget_sequence (id bigint not null, name varchar(255), primary key (id))
Hibernate: create sequence book_seq start with 1 increment by 50
Hibernate: create sequence widget_seq start with 1 increment by 25
--- inserting 30 WidgetSequence rows (GenerationType.SEQUENCE, allocationSize=25) ---
Hibernate: select next value for widget_seq
Hibernate: select next value for widget_seq
Hibernate: select next value for widget_seq
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-1]
binding parameter (2:BIGINT) <- [1]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-2]
binding parameter (2:BIGINT) <- [2]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-3]
binding parameter (2:BIGINT) <- [3]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-4]
binding parameter (2:BIGINT) <- [4]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-5]
binding parameter (2:BIGINT) <- [5]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-6]
binding parameter (2:BIGINT) <- [6]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-7]
binding parameter (2:BIGINT) <- [7]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-8]
binding parameter (2:BIGINT) <- [8]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-9]
binding parameter (2:BIGINT) <- [9]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-10]
binding parameter (2:BIGINT) <- [10]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-11]
binding parameter (2:BIGINT) <- [11]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-12]
binding parameter (2:BIGINT) <- [12]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-13]
binding parameter (2:BIGINT) <- [13]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-14]
binding parameter (2:BIGINT) <- [14]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-15]
binding parameter (2:BIGINT) <- [15]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-16]
binding parameter (2:BIGINT) <- [16]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-17]
binding parameter (2:BIGINT) <- [17]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-18]
binding parameter (2:BIGINT) <- [18]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-19]
binding parameter (2:BIGINT) <- [19]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-20]
binding parameter (2:BIGINT) <- [20]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-21]
binding parameter (2:BIGINT) <- [21]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-22]
binding parameter (2:BIGINT) <- [22]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-23]
binding parameter (2:BIGINT) <- [23]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-24]
binding parameter (2:BIGINT) <- [24]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-25]
binding parameter (2:BIGINT) <- [25]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-26]
binding parameter (2:BIGINT) <- [26]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-27]
binding parameter (2:BIGINT) <- [27]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-28]
binding parameter (2:BIGINT) <- [28]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-29]
binding parameter (2:BIGINT) <- [29]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.WidgetSequence */insert into widget_sequence (name,id) values (?,?)
binding parameter (1:VARCHAR) <- [sequence-30]
binding parameter (2:BIGINT) <- [30]
entityInsertCount = 30
prepareStatementCount = 4
(with SEQUENCE, the id is known before the row is written, so Hibernate can defer and batch the inserts -- expect prepareStatementCount well below entityInsertCount)

View File

@@ -0,0 +1,82 @@
Hibernate: select next value for book_seq
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [USER_EDIT]
binding parameter (3:VARCHAR) <- [Silent Overwrite]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [1]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
Hibernate: /* update for com.ankurm.hibernatedemo.model.Book */update book set author=?,status=?,title=?,version=? where id=? and version=?
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [ADMIN_EDIT]
binding parameter (3:VARCHAR) <- [Silent Overwrite]
binding parameter (4:BIGINT) <- [1]
binding parameter (5:BIGINT) <- [1]
binding parameter (6:BIGINT) <- [0]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
Hibernate: select next value for book_seq
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Lazy Collection Book]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [2]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Note */insert into note (book_id,text,id) values (?,?,default)
binding parameter (1:BIGINT) <- [2]
binding parameter (2:VARCHAR) <- [first note]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [2]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version,n1_0.book_id,n1_0.id,n1_0.text from book b1_0 left join note n1_0 on b1_0.id=n1_0.book_id where b1_0.id=?
binding parameter (1:BIGINT) <- [2]
Hibernate: /* update for com.ankurm.hibernatedemo.model.Book */update book set author=?,status=?,title=?,version=? where id=? and version=?
binding parameter (1:VARCHAR) <- [Edited While Detached]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Lazy Collection Book]
binding parameter (4:BIGINT) <- [1]
binding parameter (5:BIGINT) <- [2]
binding parameter (6:BIGINT) <- [0]
merge() initialized the LAZY notes collection because CascadeType.MERGE forces traversal of it
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Test Author]
binding parameter (2:VARCHAR) <- [DRAFT]
binding parameter (3:VARCHAR) <- [Managed + Detached]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [3]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [3]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [3]
Hibernate: /* update for com.ankurm.hibernatedemo.model.Book */update book set author=?,status=?,title=?,version=? where id=? and version=?
binding parameter (1:VARCHAR) <- [Changed On The Detached Copy]
binding parameter (2:VARCHAR) <- [DRAFT]
binding parameter (3:VARCHAR) <- [Managed + Detached]
binding parameter (4:BIGINT) <- [1]
binding parameter (5:BIGINT) <- [3]
binding parameter (6:BIGINT) <- [0]
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,status,title,version,id) values (?,?,?,?,?)
binding parameter (1:VARCHAR) <- [Robert C. Martin]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Clean Code]
binding parameter (4:BIGINT) <- [0]
binding parameter (5:BIGINT) <- [4]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [4]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [4]
Hibernate: /* update for com.ankurm.hibernatedemo.model.Book */update book set author=?,status=?,title=?,version=? where id=? and version=?
binding parameter (1:VARCHAR) <- [Robert C. Martin]
binding parameter (2:VARCHAR) <- [null]
binding parameter (3:VARCHAR) <- [Clean Code (2nd Edition)]
binding parameter (4:BIGINT) <- [1]
binding parameter (5:BIGINT) <- [4]
binding parameter (6:BIGINT) <- [0]
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version,n1_0.book_id,n1_0.id,n1_0.text from book b1_0 left join note n1_0 on b1_0.id=n1_0.book_id where b1_0.id=?
binding parameter (1:BIGINT) <- [4]
OptimisticLockException surfaced directly from the merge() call.
exception: jakarta.persistence.OptimisticLockException: Row was already updated or deleted by another transaction for entity [com.ankurm.hibernatedemo.model.Book with id '4']
Hibernate: select b1_0.id,b1_0.author,b1_0.status,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [4]

View File

@@ -0,0 +1,41 @@
Hibernate: create global temporary table HTE_book(rn_ integer not null, id bigint, version bigint, author varchar(255), title varchar(255), primary key (rn_)) transactional
Hibernate: create global temporary table HTE_widget_sequence(rn_ integer not null, id bigint, name varchar(255), primary key (rn_)) transactional
Hibernate: create table book (id bigint not null, author varchar(255), title varchar(255), version bigint not null, primary key (id))
Hibernate: create table widget_identity (id bigint generated by default as identity, name varchar(255), primary key (id))
Hibernate: create table widget_sequence (id bigint not null, name varchar(255), primary key (id))
Hibernate: create sequence book_seq start with 1 increment by 50
Hibernate: create sequence widget_seq start with 1 increment by 25
Hibernate: select next value for book_seq
Hibernate: /* insert for com.ankurm.hibernatedemo.model.Book */insert into book (author,title,version,id) values (?,?,?,?)
binding parameter (1:VARCHAR) <- [Robert C. Martin]
binding parameter (2:VARCHAR) <- [Clean Code]
binding parameter (3:BIGINT) <- [0]
binding parameter (4:BIGINT) <- [1]
SEED: inserted Book{id=1, title=Clean Code, author=Robert C. Martin, version=0}
--- Step 1: load the row, then close the session (entity is now detached) ---
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
detached instance in hand: Book{id=1, title=Clean Code, author=Robert C. Martin, version=0}
--- Step 2: a second, independent session edits the same row and commits ---
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
Hibernate: /* update for com.ankurm.hibernatedemo.model.Book */update book set author=?,title=?,version=? where id=? and version=?
binding parameter (1:VARCHAR) <- [Robert C. Martin]
binding parameter (2:VARCHAR) <- [Clean Code (2nd Edition)]
binding parameter (3:BIGINT) <- [1]
binding parameter (4:BIGINT) <- [1]
binding parameter (5:BIGINT) <- [0]
second session committed: Book{id=1, title=Clean Code (2nd Edition), author=Robert C. Martin, version=1} -- version column has now advanced in the database
--- Step 3: mutate the ORIGINAL detached instance (still holding the OLD version) and merge() it ---
detached instance before merge (note the version and title are both stale): Book{id=1, title=Clean Code, author=Robert C. Martin (Uncle Bob), version=0}
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
merge() threw jakarta.persistence.OptimisticLockException: Row was already updated or deleted by another transaction for entity [com.ankurm.hibernatedemo.model.Book with id '1']
the title change from Step 2 survives untouched -- merge() refused to apply a write built on a stale version
--- Step 4: refresh() on a MANAGED entity with an unflushed local edit ---
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
before refresh(): Book{id=1, title=Clean Code (2nd Edition), author=SOMEONE ELSE ENTIRELY (never flushed), version=1}
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.version from book b1_0 where b1_0.id=?
binding parameter (1:BIGINT) <- [1]
after refresh(): Book{id=1, title=Clean Code (2nd Edition), author=Robert C. Martin, version=1} -- the local edit is gone, no exception was thrown