Skip to content

Commit 2f79587

Browse files
committed
HHH-18743 make batching explicit for StatelessSession
1. ignore hibernate.jdbc.batch_size setting 2. add insertMultiple() and friends Signed-off-by: Gavin King <[email protected]>
1 parent dd8e186 commit 2f79587

File tree

5 files changed

+121
-14
lines changed

5 files changed

+121
-14
lines changed

hibernate-core/src/main/java/org/hibernate/SharedSessionContract.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ public interface SharedSessionContract extends QueryProducer, AutoCloseable, Ser
203203

204204
/**
205205
* Set the session-level JDBC batch size. Override the
206-
* {@linkplain org.hibernate.boot.spi.SessionFactoryOptions#getJdbcBatchSize() factory-level}
207-
* JDBC batch size controlled by the configuration property
206+
* {@linkplain org.hibernate.boot.spi.SessionFactoryOptions#getJdbcBatchSize
207+
* factory-level} JDBC batch size controlled by the configuration property
208208
* {@value org.hibernate.cfg.AvailableSettings#STATEMENT_BATCH_SIZE}.
209209
*
210210
* @param jdbcBatchSize the new session-level JDBC batch size

hibernate-core/src/main/java/org/hibernate/StatelessSession.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@
6060
* <li>when an exception is thrown by a stateless session, the current
6161
* transaction is not automatically marked for rollback.
6262
* </ul>
63+
* <p>
64+
* Since version 7, the configuration property
65+
* {@value org.hibernate.cfg.BatchSettings#STATEMENT_BATCH_SIZE} has no effect
66+
* on a stateless session. Automatic batching may be enabled by explicitly
67+
* {@linkplain #setJdbcBatchSize setting the batch size}. However, automatic
68+
* batching has the side effect of delaying the effect of the batched operation,
69+
* thus undermining the synchronous nature of operations performed through a
70+
* stateless session. A preferred approach is to explicitly batch operations via
71+
* {@link #insertMultiple}, {@link #updateMultiple}, or {@link #deleteMultiple}.
6372
*
6473
* @author Gavin King
6574
*/
@@ -85,6 +94,15 @@ public interface StatelessSession extends SharedSessionContract {
8594
*/
8695
Object insert(Object entity);
8796

97+
/**
98+
* Insert multiple records.
99+
*
100+
* @param entities a list of transient instances to be inserted
101+
*
102+
* @since 7.0
103+
*/
104+
void insertMultiple(List<Object> entities);
105+
88106
/**
89107
* Insert a record.
90108
* <p>
@@ -108,6 +126,15 @@ public interface StatelessSession extends SharedSessionContract {
108126
*/
109127
void update(Object entity);
110128

129+
/**
130+
* Update multiple records.
131+
*
132+
* @param entities a list of detached instances to be updated
133+
*
134+
* @since 7.0
135+
*/
136+
void updateMultiple(List<Object> entities);
137+
111138
/**
112139
* Update a record.
113140
* <p>
@@ -129,6 +156,15 @@ public interface StatelessSession extends SharedSessionContract {
129156
*/
130157
void delete(Object entity);
131158

159+
/**
160+
* Delete multiple records.
161+
*
162+
* @param entities a list of detached instances to be deleted
163+
*
164+
* @since 7.0
165+
*/
166+
void deleteMultiple(List<Object> entities);
167+
132168
/**
133169
* Delete a record.
134170
* <p>
@@ -164,6 +200,19 @@ public interface StatelessSession extends SharedSessionContract {
164200
@Incubating
165201
void upsert(Object entity);
166202

203+
/**
204+
* Perform an upsert, that is, to insert the record if it does
205+
* not exist, or update the record if it already exists, for
206+
* each given record.
207+
*
208+
* @param entities a list of detached instances and new
209+
* instances with assigned identifiers
210+
*
211+
* @since 7.0
212+
*/
213+
@Incubating
214+
void upsertMultiple(List<Object> entities);
215+
167216
/**
168217
* Use a SQL {@code merge into} statement to perform an upsert.
169218
*

hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,18 +1402,19 @@ public ExceptionConverter getExceptionConverter() {
14021402
return exceptionConverter;
14031403
}
14041404

1405+
@Override
14051406
public Integer getJdbcBatchSize() {
14061407
return jdbcBatchSize;
14071408
}
14081409

14091410
@Override
1410-
public EventManager getEventManager() {
1411-
return fastSessionServices.getEventManager();
1411+
public void setJdbcBatchSize(Integer jdbcBatchSize) {
1412+
this.jdbcBatchSize = jdbcBatchSize;
14121413
}
14131414

14141415
@Override
1415-
public void setJdbcBatchSize(Integer jdbcBatchSize) {
1416-
this.jdbcBatchSize = jdbcBatchSize;
1416+
public EventManager getEventManager() {
1417+
return fastSessionServices.getEventManager();
14171418
}
14181419

14191420
@Override

hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public StatelessSessionImpl(SessionFactoryImpl factory, SessionCreationOptions o
105105
temporaryPersistenceContext = new StatefulPersistenceContext( this );
106106
influencers = new LoadQueryInfluencers( getFactory() );
107107
setUpMultitenancy( factory, influencers );
108+
setJdbcBatchSize( 0 );
108109
}
109110

110111
@Override
@@ -119,6 +120,20 @@ public Object insert(Object entity) {
119120
return insert( null, entity );
120121
}
121122

123+
@Override
124+
public void insertMultiple(List<Object> entities) {
125+
final Integer batchSize = getJdbcBatchSize();
126+
setJdbcBatchSize( entities.size() );
127+
try {
128+
for ( Object entity : entities ) {
129+
insert( null, entity );
130+
}
131+
}
132+
finally {
133+
setJdbcBatchSize( batchSize );
134+
}
135+
}
136+
122137
@Override
123138
public Object insert(String entityName, Object entity) {
124139
checkOpen();
@@ -180,6 +195,20 @@ public void delete(Object entity) {
180195
delete( null, entity );
181196
}
182197

198+
@Override
199+
public void deleteMultiple(List<Object> entities) {
200+
final Integer batchSize = getJdbcBatchSize();
201+
setJdbcBatchSize( entities.size() );
202+
try {
203+
for ( Object entity : entities ) {
204+
delete( null, entity );
205+
}
206+
}
207+
finally {
208+
setJdbcBatchSize( batchSize );
209+
}
210+
}
211+
183212
@Override
184213
public void delete(String entityName, Object entity) {
185214
checkOpen();
@@ -215,8 +244,17 @@ public void update(Object entity) {
215244
}
216245

217246
@Override
218-
public void upsert(Object entity) {
219-
upsert( null, entity );
247+
public void updateMultiple(List<Object> entities) {
248+
final Integer batchSize = getJdbcBatchSize();
249+
setJdbcBatchSize( entities.size() );
250+
try {
251+
for ( Object entity : entities ) {
252+
update( null, entity );
253+
}
254+
}
255+
finally {
256+
setJdbcBatchSize( batchSize );
257+
}
220258
}
221259

222260
@Override
@@ -257,6 +295,25 @@ public void update(String entityName, Object entity) {
257295
}
258296
}
259297

298+
@Override
299+
public void upsert(Object entity) {
300+
upsert( null, entity );
301+
}
302+
303+
@Override
304+
public void upsertMultiple(List<Object> entities) {
305+
final Integer batchSize = getJdbcBatchSize();
306+
setJdbcBatchSize( entities.size() );
307+
try {
308+
for ( Object entity : entities ) {
309+
upsert( null, entity );
310+
}
311+
}
312+
finally {
313+
setJdbcBatchSize( batchSize );
314+
}
315+
}
316+
260317
@Override
261318
public void upsert(String entityName, Object entity) {
262319
checkOpen();

hibernate-core/src/main/java/org/hibernate/resource/jdbc/spi/JdbcSessionOwner.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
/**
1313
* Contract for something that controls a {@link JdbcSessionContext}.
1414
* <p>
15-
* The term "JDBC session" is taken from the SQL specification which
15+
* The term <em>JDBC session</em> is taken from the SQL specification which
1616
* calls a connection and its associated transaction context a "session".
1717
*
1818
* @apiNote The name comes from the design idea of a {@code JdbcSession}
@@ -28,9 +28,9 @@ public interface JdbcSessionOwner {
2828
JdbcConnectionAccess getJdbcConnectionAccess();
2929

3030
/**
31-
* Obtain the builder for TransactionCoordinator instances
31+
* Obtain the builder for {@link TransactionCoordinator} instances
3232
*
33-
* @return The TransactionCoordinatorBuilder
33+
* @return The {@code TransactionCoordinator}
3434
*/
3535
TransactionCoordinator getTransactionCoordinator();
3636

@@ -43,7 +43,7 @@ public interface JdbcSessionOwner {
4343
void startTransactionBoundary();
4444

4545
/**
46-
* A after-begin callback from the coordinator to its owner.
46+
* An after-begin callback from the coordinator to its owner.
4747
*/
4848
void afterTransactionBegin();
4949

@@ -63,8 +63,8 @@ public interface JdbcSessionOwner {
6363
void flushBeforeTransactionCompletion();
6464

6565
/**
66-
* Get the Session-level JDBC batch size.
67-
* @return Session-level JDBC batch size
66+
* Get the session-level JDBC batch size.
67+
* @return session-level JDBC batch size
6868
*
6969
* @since 5.2
7070
*/

0 commit comments

Comments
 (0)