HHH-18743 make batching explicit for StatelessSession
1. ignore hibernate.jdbc.batch_size setting 2. add insertMultiple() and friends Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
dd8e186416
commit
f82c581990
|
@ -203,8 +203,8 @@ public interface SharedSessionContract extends QueryProducer, AutoCloseable, Ser
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the session-level JDBC batch size. Override the
|
* Set the session-level JDBC batch size. Override the
|
||||||
* {@linkplain org.hibernate.boot.spi.SessionFactoryOptions#getJdbcBatchSize() factory-level}
|
* {@linkplain org.hibernate.boot.spi.SessionFactoryOptions#getJdbcBatchSize
|
||||||
* JDBC batch size controlled by the configuration property
|
* factory-level} JDBC batch size controlled by the configuration property
|
||||||
* {@value org.hibernate.cfg.AvailableSettings#STATEMENT_BATCH_SIZE}.
|
* {@value org.hibernate.cfg.AvailableSettings#STATEMENT_BATCH_SIZE}.
|
||||||
*
|
*
|
||||||
* @param jdbcBatchSize the new session-level JDBC batch size
|
* @param jdbcBatchSize the new session-level JDBC batch size
|
||||||
|
|
|
@ -60,6 +60,15 @@ import java.util.List;
|
||||||
* <li>when an exception is thrown by a stateless session, the current
|
* <li>when an exception is thrown by a stateless session, the current
|
||||||
* transaction is not automatically marked for rollback.
|
* transaction is not automatically marked for rollback.
|
||||||
* </ul>
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* Since version 7, the configuration property
|
||||||
|
* {@value org.hibernate.cfg.BatchSettings#STATEMENT_BATCH_SIZE} has no effect
|
||||||
|
* on a stateless session. Automatic batching may be enabled by explicitly
|
||||||
|
* {@linkplain #setJdbcBatchSize setting the batch size}. However, automatic
|
||||||
|
* batching has the side effect of delaying execution of the batched operation,
|
||||||
|
* thus undermining the synchronous nature of operations performed through a
|
||||||
|
* stateless session. A preferred approach is to explicitly batch operations via
|
||||||
|
* {@link #insertMultiple}, {@link #updateMultiple}, or {@link #deleteMultiple}.
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
|
@ -85,6 +94,16 @@ public interface StatelessSession extends SharedSessionContract {
|
||||||
*/
|
*/
|
||||||
Object insert(Object entity);
|
Object insert(Object entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert multiple records.
|
||||||
|
*
|
||||||
|
* @param entities a list of transient instances to be inserted
|
||||||
|
*
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
void insertMultiple(List<Object> entities);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert a record.
|
* Insert a record.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -108,6 +127,16 @@ public interface StatelessSession extends SharedSessionContract {
|
||||||
*/
|
*/
|
||||||
void update(Object entity);
|
void update(Object entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update multiple records.
|
||||||
|
*
|
||||||
|
* @param entities a list of detached instances to be updated
|
||||||
|
*
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
void updateMultiple(List<Object> entities);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a record.
|
* Update a record.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -129,6 +158,16 @@ public interface StatelessSession extends SharedSessionContract {
|
||||||
*/
|
*/
|
||||||
void delete(Object entity);
|
void delete(Object entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete multiple records.
|
||||||
|
*
|
||||||
|
* @param entities a list of detached instances to be deleted
|
||||||
|
*
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
void deleteMultiple(List<Object> entities);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a record.
|
* Delete a record.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -164,6 +203,19 @@ public interface StatelessSession extends SharedSessionContract {
|
||||||
@Incubating
|
@Incubating
|
||||||
void upsert(Object entity);
|
void upsert(Object entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an upsert, that is, to insert the record if it does
|
||||||
|
* not exist, or update the record if it already exists, for
|
||||||
|
* each given record.
|
||||||
|
*
|
||||||
|
* @param entities a list of detached instances and new
|
||||||
|
* instances with assigned identifiers
|
||||||
|
*
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
void upsertMultiple(List<Object> entities);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use a SQL {@code merge into} statement to perform an upsert.
|
* Use a SQL {@code merge into} statement to perform an upsert.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1402,18 +1402,19 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
return exceptionConverter;
|
return exceptionConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Integer getJdbcBatchSize() {
|
public Integer getJdbcBatchSize() {
|
||||||
return jdbcBatchSize;
|
return jdbcBatchSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventManager getEventManager() {
|
public void setJdbcBatchSize(Integer jdbcBatchSize) {
|
||||||
return fastSessionServices.getEventManager();
|
this.jdbcBatchSize = jdbcBatchSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setJdbcBatchSize(Integer jdbcBatchSize) {
|
public EventManager getEventManager() {
|
||||||
this.jdbcBatchSize = jdbcBatchSize;
|
return fastSessionServices.getEventManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -105,6 +105,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
||||||
temporaryPersistenceContext = new StatefulPersistenceContext( this );
|
temporaryPersistenceContext = new StatefulPersistenceContext( this );
|
||||||
influencers = new LoadQueryInfluencers( getFactory() );
|
influencers = new LoadQueryInfluencers( getFactory() );
|
||||||
setUpMultitenancy( factory, influencers );
|
setUpMultitenancy( factory, influencers );
|
||||||
|
setJdbcBatchSize( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -119,6 +120,20 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
||||||
return insert( null, entity );
|
return insert( null, entity );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertMultiple(List<Object> entities) {
|
||||||
|
final Integer batchSize = getJdbcBatchSize();
|
||||||
|
setJdbcBatchSize( entities.size() );
|
||||||
|
try {
|
||||||
|
for ( Object entity : entities ) {
|
||||||
|
insert( null, entity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setJdbcBatchSize( batchSize );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object insert(String entityName, Object entity) {
|
public Object insert(String entityName, Object entity) {
|
||||||
checkOpen();
|
checkOpen();
|
||||||
|
@ -180,6 +195,20 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
||||||
delete( null, entity );
|
delete( null, entity );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteMultiple(List<Object> entities) {
|
||||||
|
final Integer batchSize = getJdbcBatchSize();
|
||||||
|
setJdbcBatchSize( entities.size() );
|
||||||
|
try {
|
||||||
|
for ( Object entity : entities ) {
|
||||||
|
delete( null, entity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setJdbcBatchSize( batchSize );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(String entityName, Object entity) {
|
public void delete(String entityName, Object entity) {
|
||||||
checkOpen();
|
checkOpen();
|
||||||
|
@ -215,8 +244,17 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void upsert(Object entity) {
|
public void updateMultiple(List<Object> entities) {
|
||||||
upsert( null, entity );
|
final Integer batchSize = getJdbcBatchSize();
|
||||||
|
setJdbcBatchSize( entities.size() );
|
||||||
|
try {
|
||||||
|
for ( Object entity : entities ) {
|
||||||
|
update( null, entity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setJdbcBatchSize( batchSize );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -257,6 +295,25 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void upsert(Object entity) {
|
||||||
|
upsert( null, entity );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void upsertMultiple(List<Object> entities) {
|
||||||
|
final Integer batchSize = getJdbcBatchSize();
|
||||||
|
setJdbcBatchSize( entities.size() );
|
||||||
|
try {
|
||||||
|
for ( Object entity : entities ) {
|
||||||
|
upsert( null, entity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setJdbcBatchSize( batchSize );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void upsert(String entityName, Object entity) {
|
public void upsert(String entityName, Object entity) {
|
||||||
checkOpen();
|
checkOpen();
|
||||||
|
|
|
@ -12,7 +12,7 @@ import org.hibernate.resource.transaction.spi.TransactionCoordinator;
|
||||||
/**
|
/**
|
||||||
* Contract for something that controls a {@link JdbcSessionContext}.
|
* Contract for something that controls a {@link JdbcSessionContext}.
|
||||||
* <p>
|
* <p>
|
||||||
* The term "JDBC session" is taken from the SQL specification which
|
* The term <em>JDBC session</em> is taken from the SQL specification which
|
||||||
* calls a connection and its associated transaction context a "session".
|
* calls a connection and its associated transaction context a "session".
|
||||||
*
|
*
|
||||||
* @apiNote The name comes from the design idea of a {@code JdbcSession}
|
* @apiNote The name comes from the design idea of a {@code JdbcSession}
|
||||||
|
@ -28,9 +28,9 @@ public interface JdbcSessionOwner {
|
||||||
JdbcConnectionAccess getJdbcConnectionAccess();
|
JdbcConnectionAccess getJdbcConnectionAccess();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain the builder for TransactionCoordinator instances
|
* Obtain the {@link TransactionCoordinator}.
|
||||||
*
|
*
|
||||||
* @return The TransactionCoordinatorBuilder
|
* @return The {@code TransactionCoordinator}
|
||||||
*/
|
*/
|
||||||
TransactionCoordinator getTransactionCoordinator();
|
TransactionCoordinator getTransactionCoordinator();
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ public interface JdbcSessionOwner {
|
||||||
void startTransactionBoundary();
|
void startTransactionBoundary();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A after-begin callback from the coordinator to its owner.
|
* An after-begin callback from the coordinator to its owner.
|
||||||
*/
|
*/
|
||||||
void afterTransactionBegin();
|
void afterTransactionBegin();
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ public interface JdbcSessionOwner {
|
||||||
void flushBeforeTransactionCompletion();
|
void flushBeforeTransactionCompletion();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Session-level JDBC batch size.
|
* Get the session-level JDBC batch size.
|
||||||
* @return Session-level JDBC batch size
|
* @return session-level JDBC batch size
|
||||||
*
|
*
|
||||||
* @since 5.2
|
* @since 5.2
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -340,6 +340,14 @@ must be explicitly set to true.
|
||||||
|
|
||||||
The signature of the `Configurable#configure` method changed from accepting just a `ServiceRegistry` instance to the new `GeneratorCreationContext` interface, which exposes a lot more useful information when configuring the generator itself. The old signature has been deprecated for removal, so you should migrate any custom `Configurable` generator implementation to the new one.
|
The signature of the `Configurable#configure` method changed from accepting just a `ServiceRegistry` instance to the new `GeneratorCreationContext` interface, which exposes a lot more useful information when configuring the generator itself. The old signature has been deprecated for removal, so you should migrate any custom `Configurable` generator implementation to the new one.
|
||||||
|
|
||||||
|
[[stateless-session-jdbc-batching]]
|
||||||
|
== JDBC batching with `StatelessSession`
|
||||||
|
|
||||||
|
Automatic JDBC batching has the side effect of delaying the execution of the batched operation, and this undermines the synchronous nature of operations performed through a stateless session.
|
||||||
|
In Hibernate 7, the configuration property `hibernate.jdbc.batch_size` now has no effect on a stateless session.
|
||||||
|
Automatic batching may be enabled by explicitly calling `setJdbcBatchSize()`.
|
||||||
|
However, the preferred approach is to explicitly batch operations via `insertMultiple()`, `updateMultiple()`, or `deleteMultiple()`.
|
||||||
|
|
||||||
[[hbm-transform]]
|
[[hbm-transform]]
|
||||||
== hbm.xml Transformation
|
== hbm.xml Transformation
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue