HHH-17073 Auto flush broken when using sequence generator ID
This commit is contained in:
parent
7a4523a470
commit
fe77bcfee9
|
@ -38,6 +38,7 @@ import org.hibernate.engine.jdbc.LobCreator;
|
|||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.event.spi.AutoFlushEvent;
|
||||
import org.hibernate.event.spi.EventManager;
|
||||
import org.hibernate.event.spi.DeleteContext;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
|
@ -397,6 +398,17 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
|
|||
return delegate.autoFlushIfRequired( querySpaces );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean autoFlushIfRequired(Set<String> querySpaces, boolean skipPreFlush)
|
||||
throws HibernateException {
|
||||
return delegate.autoFlushIfRequired( querySpaces, skipPreFlush );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autoPreFlush() {
|
||||
delegate.autoPreFlush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterOperation(boolean success) {
|
||||
delegate.afterOperation( success );
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.event.spi.AutoFlushEvent;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.graph.GraphSemantic;
|
||||
import org.hibernate.query.Query;
|
||||
|
@ -537,6 +538,14 @@ public interface SharedSessionContractImplementor
|
|||
*/
|
||||
boolean autoFlushIfRequired(Set<String> querySpaces) throws HibernateException;
|
||||
|
||||
default boolean autoFlushIfRequired(Set<String> querySpaces, boolean skipPreFlush)
|
||||
throws HibernateException {
|
||||
return autoFlushIfRequired( querySpaces );
|
||||
}
|
||||
|
||||
default void autoPreFlush(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we currently enforcing a {@linkplain GraphSemantic#FETCH fetch graph}?
|
||||
*
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.hibernate.engine.jdbc.LobCreator;
|
|||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.event.spi.AutoFlushEvent;
|
||||
import org.hibernate.event.spi.EventManager;
|
||||
import org.hibernate.graph.RootGraph;
|
||||
import org.hibernate.jdbc.ReturningWork;
|
||||
|
@ -558,6 +559,17 @@ public class SharedSessionDelegatorBaseImpl implements SharedSessionContractImpl
|
|||
return delegate.autoFlushIfRequired( querySpaces );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean autoFlushIfRequired(Set<String> querySpaces, boolean skipPreFlush)
|
||||
throws HibernateException {
|
||||
return delegate.autoFlushIfRequired( querySpaces, skipPreFlush );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autoPreFlush() {
|
||||
delegate.autoPreFlush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterOperation(boolean success) {
|
||||
delegate.afterOperation( success );
|
||||
|
|
|
@ -74,6 +74,29 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
|
|||
final EventSource session = event.getSession();
|
||||
|
||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
||||
preFlush( session, persistenceContext );
|
||||
|
||||
flushEverythingToExecutions( event, persistenceContext, session );
|
||||
}
|
||||
|
||||
protected void flushEverythingToExecutions(FlushEvent event, PersistenceContext persistenceContext, EventSource session) {
|
||||
persistenceContext.setFlushing( true );
|
||||
try {
|
||||
int entityCount = flushEntities( event, persistenceContext );
|
||||
int collectionCount = flushCollections( session, persistenceContext );
|
||||
|
||||
event.setNumberOfEntitiesProcessed( entityCount );
|
||||
event.setNumberOfCollectionsProcessed( collectionCount );
|
||||
}
|
||||
finally {
|
||||
persistenceContext.setFlushing( false);
|
||||
}
|
||||
|
||||
//some statistics
|
||||
logFlushResults( event );
|
||||
}
|
||||
|
||||
protected void preFlush(EventSource session, PersistenceContext persistenceContext) {
|
||||
session.getInterceptor().preFlush( persistenceContext.managedEntitiesIterator() );
|
||||
|
||||
prepareEntityFlushes( session, persistenceContext );
|
||||
|
@ -84,21 +107,6 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
|
|||
// now, any collections that are initialized
|
||||
// inside this block do not get updated - they
|
||||
// are ignored until the next flush
|
||||
|
||||
persistenceContext.setFlushing( true );
|
||||
try {
|
||||
int entityCount = flushEntities( event, persistenceContext );
|
||||
int collectionCount = flushCollections( session, persistenceContext );
|
||||
|
||||
event.setNumberOfEntitiesProcessed( entityCount );
|
||||
event.setNumberOfCollectionsProcessed( collectionCount );
|
||||
}
|
||||
finally {
|
||||
persistenceContext.setFlushing(false);
|
||||
}
|
||||
|
||||
//some statistics
|
||||
logFlushResults( event );
|
||||
}
|
||||
|
||||
protected void logFlushResults(FlushEvent event) {
|
||||
|
|
|
@ -48,8 +48,13 @@ public class DefaultAutoFlushEventListener extends AbstractFlushingEventListener
|
|||
// Need to get the number of collection removals before flushing to executions
|
||||
// (because flushing to executions can add collection removal actions to the action queue).
|
||||
final ActionQueue actionQueue = source.getActionQueue();
|
||||
final EventSource session = event.getSession();
|
||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
||||
if ( !event.isSkipPreFlush() ) {
|
||||
preFlush( session, persistenceContext );
|
||||
}
|
||||
final int oldSize = actionQueue.numberOfCollectionRemovals();
|
||||
flushEverythingToExecutions( event );
|
||||
flushEverythingToExecutions( event, persistenceContext, session );
|
||||
if ( flushIsReallyNeeded( event, source ) ) {
|
||||
LOG.trace( "Need to execute flush" );
|
||||
event.setFlushRequired( true );
|
||||
|
@ -87,6 +92,13 @@ public class DefaultAutoFlushEventListener extends AbstractFlushingEventListener
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutoPreFlush(EventSource source) {
|
||||
if ( flushMightBeNeeded( source ) ) {
|
||||
preFlush( source, source.getPersistenceContextInternal() );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean flushIsReallyNeeded(AutoFlushEvent event, final EventSource source) {
|
||||
return source.getHibernateFlushMode() == FlushMode.ALWAYS
|
||||
|| source.getActionQueue().areTablesToBeUpdated( event.getQuerySpaces() );
|
||||
|
|
|
@ -16,10 +16,16 @@ public class AutoFlushEvent extends FlushEvent {
|
|||
|
||||
private Set<String> querySpaces;
|
||||
private boolean flushRequired;
|
||||
private boolean skipPreFlush;
|
||||
|
||||
public AutoFlushEvent(Set<String> querySpaces, EventSource source) {
|
||||
super(source);
|
||||
this( querySpaces, false, source );
|
||||
}
|
||||
|
||||
public AutoFlushEvent(Set<String> querySpaces, boolean skipPreFlush, EventSource source) {
|
||||
super( source );
|
||||
this.querySpaces = querySpaces;
|
||||
this.skipPreFlush = skipPreFlush;
|
||||
}
|
||||
|
||||
public Set<String> getQuerySpaces() {
|
||||
|
@ -37,4 +43,8 @@ public class AutoFlushEvent extends FlushEvent {
|
|||
public void setFlushRequired(boolean dirty) {
|
||||
this.flushRequired = dirty;
|
||||
}
|
||||
|
||||
public boolean isSkipPreFlush() {
|
||||
return skipPreFlush;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.event.spi;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.SharedSessionContract;
|
||||
|
||||
/**
|
||||
* Defines the contract for handling of session auto-flush events.
|
||||
|
@ -20,4 +21,7 @@ public interface AutoFlushEventListener {
|
|||
* @param event The auto-flush event to be handled.
|
||||
*/
|
||||
void onAutoFlush(AutoFlushEvent event) throws HibernateException;
|
||||
|
||||
default void onAutoPreFlush(EventSource source) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1359,17 +1359,36 @@ public class SessionImpl
|
|||
|
||||
@Override
|
||||
public boolean autoFlushIfRequired(Set<String> querySpaces) throws HibernateException {
|
||||
return autoFlushIfRequired( querySpaces, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean autoFlushIfRequired(Set<String> querySpaces, boolean skipPreFlush)
|
||||
throws HibernateException {
|
||||
checkOpen();
|
||||
if ( !isTransactionInProgress() ) {
|
||||
// do not auto-flush while outside a transaction
|
||||
return false;
|
||||
}
|
||||
AutoFlushEvent event = new AutoFlushEvent( querySpaces, this );
|
||||
AutoFlushEvent event = new AutoFlushEvent( querySpaces, skipPreFlush, this );
|
||||
fastSessionServices.eventListenerGroup_AUTO_FLUSH
|
||||
.fireEventOnEachListener( event, AutoFlushEventListener::onAutoFlush );
|
||||
return event.isFlushRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autoPreFlush(){
|
||||
checkOpen();
|
||||
if ( !isTransactionInProgress() ) {
|
||||
// do not auto-flush while outside a transaction
|
||||
return;
|
||||
}
|
||||
fastSessionServices.eventListenerGroup_AUTO_FLUSH
|
||||
.fireEventOnEachListener( this, AutoFlushEventListener::onAutoPreFlush );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDirty() throws HibernateException {
|
||||
checkOpen();
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
|||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.event.spi.AutoFlushEvent;
|
||||
import org.hibernate.generator.BeforeExecutionGenerator;
|
||||
import org.hibernate.generator.Generator;
|
||||
import org.hibernate.generator.values.GeneratedValues;
|
||||
|
|
|
@ -12,12 +12,14 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import jakarta.persistence.Tuple;
|
||||
|
||||
import org.hibernate.InstantiationException;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.engine.spi.EntityHolder;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.engine.spi.SubselectFetch;
|
||||
import org.hibernate.event.spi.AutoFlushEvent;
|
||||
import org.hibernate.internal.EmptyScrollableResults;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
||||
import org.hibernate.query.Query;
|
||||
|
@ -105,7 +107,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
JdbcParametersList.empty(),
|
||||
jdbcParameterBindings
|
||||
);
|
||||
|
||||
session.autoFlushIfRequired( jdbcSelect.getAffectedTableNames(), true );
|
||||
return session.getFactory().getJdbcServices().getJdbcSelectExecutor().executeQuery(
|
||||
jdbcSelect,
|
||||
jdbcParameterBindings,
|
||||
|
@ -133,8 +135,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
JdbcParametersList.empty(),
|
||||
jdbcParameterBindings
|
||||
);
|
||||
|
||||
session.autoFlushIfRequired( jdbcSelect.getAffectedTableNames() );
|
||||
session.autoFlushIfRequired( jdbcSelect.getAffectedTableNames(), true );
|
||||
return session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
jdbcParameterBindings,
|
||||
|
@ -162,7 +163,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
final JdbcSelectExecutor jdbcSelectExecutor = session.getFactory()
|
||||
.getJdbcServices()
|
||||
.getJdbcSelectExecutor();
|
||||
session.autoFlushIfRequired( jdbcSelect.getAffectedTableNames() );
|
||||
session.autoFlushIfRequired( jdbcSelect.getAffectedTableNames(), true );
|
||||
return jdbcSelectExecutor.scroll(
|
||||
jdbcSelect,
|
||||
scrollMode,
|
||||
|
@ -204,7 +205,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
return selections.size() == 1 ? selections.get( 0 ) : null;
|
||||
}
|
||||
|
||||
private static final Map<Class<?>,Class<?>> WRAPPERS
|
||||
private static final Map<Class<?>, Class<?>> WRAPPERS
|
||||
= Map.of(
|
||||
boolean.class, Boolean.class,
|
||||
int.class, Integer.class,
|
||||
|
@ -318,6 +319,8 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
CacheableSqmInterpretation localCopy = cacheableSqmInterpretation;
|
||||
JdbcParameterBindings jdbcParameterBindings = null;
|
||||
|
||||
executionContext.getSession().autoPreFlush();
|
||||
|
||||
if ( localCopy == null ) {
|
||||
synchronized ( this ) {
|
||||
localCopy = cacheableSqmInterpretation;
|
||||
|
|
Loading…
Reference in New Issue