HHH-15976 Introduce InitializersList helper and optimise Row processing
This commit is contained in:
parent
e1ecf734c2
commit
04becd0aa4
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.sql.results.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchInitializer;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchInitializer;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
|
||||
/**
|
||||
* Internal helper to keep track of the various
|
||||
* Initializer instances being used during RowReader processing:
|
||||
* different types of initializers need to be invoked in different orders,
|
||||
* so rather than finding them during each row we keep separated lists
|
||||
* of initializers defined upfront and then reused for the scope of the whole
|
||||
* resultset.
|
||||
*/
|
||||
public final class InitializersList {
|
||||
private final List<Initializer> initializers;
|
||||
private final List<Initializer> collectionInitializers;
|
||||
private final List<Initializer> nonCollectionInitializers;
|
||||
private final List<Initializer> resolveInstanceFirstInitializers;
|
||||
private final List<Initializer> resolveInstanceLaterInitializers;
|
||||
private final boolean hasCollectionInitializers;
|
||||
private final Map<NavigablePath, Initializer> initializerMap;
|
||||
|
||||
private InitializersList(
|
||||
List<Initializer> initializers,
|
||||
List<Initializer> collectionInitializers,
|
||||
List<Initializer> nonCollectionInitializers,
|
||||
List<Initializer> resolveInstanceFirstInitializers,
|
||||
List<Initializer> resolveInstanceLaterInitializers,
|
||||
Map<NavigablePath, Initializer> initializerMap) {
|
||||
this.initializers = initializers;
|
||||
this.collectionInitializers = collectionInitializers;
|
||||
this.nonCollectionInitializers = nonCollectionInitializers;
|
||||
this.resolveInstanceFirstInitializers = resolveInstanceFirstInitializers;
|
||||
this.resolveInstanceLaterInitializers = resolveInstanceLaterInitializers;
|
||||
this.hasCollectionInitializers = ! collectionInitializers.isEmpty();
|
||||
this.initializerMap = initializerMap;
|
||||
}
|
||||
|
||||
@Deprecated //for simpler migration to the new SPI
|
||||
public List<Initializer> asList() {
|
||||
return initializers;
|
||||
}
|
||||
|
||||
public Initializer resolveInitializer(final NavigablePath path) {
|
||||
return initializerMap.get( path );
|
||||
}
|
||||
|
||||
public void finishUpRow(final RowProcessingState rowProcessingState) {
|
||||
for ( Initializer init : initializers ) {
|
||||
init.finishUpRow( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
public void initializeInstance(final RowProcessingState rowProcessingState) {
|
||||
for ( Initializer init : initializers ) {
|
||||
init.initializeInstance( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
public void endLoading(final ExecutionContext executionContext) {
|
||||
for ( Initializer initializer : initializers ) {
|
||||
initializer.endLoading( executionContext );
|
||||
}
|
||||
}
|
||||
|
||||
public void resolveKeys(final RowProcessingState rowProcessingState) {
|
||||
for ( Initializer init : nonCollectionInitializers ) {
|
||||
init.resolveKey( rowProcessingState );
|
||||
}
|
||||
for ( Initializer init : collectionInitializers ) {
|
||||
init.resolveKey( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
public void resolveInstances(final RowProcessingState rowProcessingState) {
|
||||
for ( Initializer init : resolveInstanceFirstInitializers ) {
|
||||
init.resolveInstance( rowProcessingState );
|
||||
}
|
||||
for ( Initializer init : resolveInstanceLaterInitializers ) {
|
||||
init.resolveInstance( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasCollectionInitializers() {
|
||||
return this.hasCollectionInitializers;
|
||||
}
|
||||
|
||||
static class Builder {
|
||||
private List<Initializer> initializers = new ArrayList<>();
|
||||
private List<Initializer> collectionInitializers;
|
||||
private List<Initializer> nonCollectionInitializers;
|
||||
private List<Initializer> resolveInstanceFirstInitializers;
|
||||
private List<Initializer> resolveInstanceLaterInitializers;
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public void addInitializer(Initializer initializer) {
|
||||
initializers.add( initializer );
|
||||
if ( initializer.isCollectionInitializer() ) {
|
||||
if ( collectionInitializers == null ) {
|
||||
collectionInitializers = new ArrayList<>();
|
||||
}
|
||||
collectionInitializers.add( initializer );
|
||||
}
|
||||
else {
|
||||
if ( nonCollectionInitializers == null ) {
|
||||
nonCollectionInitializers = new ArrayList<>();
|
||||
}
|
||||
nonCollectionInitializers.add( initializer );
|
||||
}
|
||||
if ( !( initializer instanceof EntityDelayedFetchInitializer ) && ! (initializer instanceof EntitySelectFetchInitializer ) ) {
|
||||
if ( resolveInstanceFirstInitializers == null ) {
|
||||
resolveInstanceFirstInitializers = new ArrayList<>();
|
||||
}
|
||||
resolveInstanceFirstInitializers.add( initializer );
|
||||
}
|
||||
else {
|
||||
if ( resolveInstanceLaterInitializers == null ) {
|
||||
resolveInstanceLaterInitializers = new ArrayList<>();
|
||||
}
|
||||
resolveInstanceLaterInitializers.add( initializer );
|
||||
}
|
||||
}
|
||||
|
||||
InitializersList build(Map<NavigablePath, Initializer> initializerMap) {
|
||||
return new InitializersList(
|
||||
initializers,
|
||||
collectionInitializers == null ? Collections.EMPTY_LIST : collectionInitializers,
|
||||
nonCollectionInitializers == null ? Collections.EMPTY_LIST : nonCollectionInitializers,
|
||||
resolveInstanceFirstInitializers == null ? Collections.EMPTY_LIST : resolveInstanceFirstInitializers,
|
||||
resolveInstanceLaterInitializers == null ? Collections.EMPTY_LIST : resolveInstanceLaterInitializers,
|
||||
initializerMap
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -73,7 +73,7 @@ public class ResultsHelper {
|
|||
final SessionFactoryImplementor sessionFactory = executionContext.getSession().getFactory();
|
||||
|
||||
final Map<NavigablePath, Initializer> initializerMap = new LinkedHashMap<>();
|
||||
final List<Initializer> initializers = new ArrayList<>();
|
||||
final InitializersList.Builder initializersBuilder = new InitializersList.Builder();
|
||||
|
||||
final List<DomainResultAssembler<?>> assemblers = jdbcValuesMapping.resolveAssemblers(
|
||||
new AssemblerCreationState() {
|
||||
|
@ -112,7 +112,7 @@ public class ResultsHelper {
|
|||
);
|
||||
|
||||
initializerMap.put( navigablePath, initializer );
|
||||
initializers.add( initializer );
|
||||
initializersBuilder.addInitializer( initializer );
|
||||
|
||||
return initializer;
|
||||
}
|
||||
|
@ -126,7 +126,9 @@ public class ResultsHelper {
|
|||
|
||||
logInitializers( initializerMap );
|
||||
|
||||
return new StandardRowReader<>( assemblers, initializers, rowTransformer, transformedResultJavaType );
|
||||
final InitializersList initializersList = initializersBuilder.build( initializerMap );
|
||||
|
||||
return new StandardRowReader<>( assemblers, initializersList, rowTransformer, transformedResultJavaType );
|
||||
}
|
||||
|
||||
private static void logInitializers(Map<NavigablePath, Initializer> initializerMap) {
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.internal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
|
@ -28,16 +26,14 @@ import org.hibernate.sql.results.spi.RowReader;
|
|||
* Standard RowProcessingState implementation
|
||||
*/
|
||||
public class RowProcessingStateStandardImpl extends BaseExecutionContext implements RowProcessingState {
|
||||
private static final Initializer[] NO_INITIALIZERS = new Initializer[0];
|
||||
|
||||
private final JdbcValuesSourceProcessingStateStandardImpl resultSetProcessingState;
|
||||
|
||||
private final Initializer[] initializers;
|
||||
private final InitializersList initializers;
|
||||
|
||||
private final RowReader<?> rowReader;
|
||||
private final JdbcValues jdbcValues;
|
||||
private final ExecutionContext executionContext;
|
||||
public final boolean hasCollectionInitializers;
|
||||
|
||||
public RowProcessingStateStandardImpl(
|
||||
JdbcValuesSourceProcessingStateStandardImpl resultSetProcessingState,
|
||||
|
@ -49,30 +45,7 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme
|
|||
this.executionContext = executionContext;
|
||||
this.rowReader = rowReader;
|
||||
this.jdbcValues = jdbcValues;
|
||||
|
||||
final List<Initializer> initializers = rowReader.getInitializers();
|
||||
if ( initializers == null || initializers.isEmpty() ) {
|
||||
this.initializers = NO_INITIALIZERS;
|
||||
hasCollectionInitializers = false;
|
||||
}
|
||||
else {
|
||||
//noinspection ToArrayCallWithZeroLengthArrayArgument
|
||||
this.initializers = initializers.toArray( new Initializer[initializers.size()] );
|
||||
hasCollectionInitializers = hasCollectionInitializers(this.initializers);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasCollectionInitializers(Initializer[] initializers) {
|
||||
for ( int i = 0; i < initializers.length; i++ ) {
|
||||
if ( initializers[i].isCollectionInitializer() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasCollectionInitializers(){
|
||||
return this.hasCollectionInitializers;
|
||||
this.initializers = rowReader.getInitializersList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -177,12 +150,10 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme
|
|||
|
||||
@Override
|
||||
public Initializer resolveInitializer(NavigablePath path) {
|
||||
for ( Initializer initializer : initializers ) {
|
||||
if ( initializer.getNavigablePath().equals( path ) ) {
|
||||
return initializer;
|
||||
}
|
||||
return this.initializers.resolveInitializer( path );
|
||||
}
|
||||
|
||||
return null;
|
||||
public boolean hasCollectionInitializers() {
|
||||
return this.initializers.hasCollectionInitializers();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ import org.hibernate.query.named.RowReaderMemento;
|
|||
import org.hibernate.sql.results.LoadingLogger;
|
||||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchInitializer;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchInitializer;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
|
@ -30,7 +28,7 @@ import org.hibernate.type.descriptor.java.JavaType;
|
|||
@SuppressWarnings("rawtypes")
|
||||
public class StandardRowReader<T> implements RowReader<T> {
|
||||
private final List<DomainResultAssembler<?>> resultAssemblers;
|
||||
private final List<Initializer> initializers;
|
||||
private final InitializersList initializers;
|
||||
private final RowTransformer<T> rowTransformer;
|
||||
private final Class<T> domainResultJavaType;
|
||||
|
||||
|
@ -38,7 +36,7 @@ public class StandardRowReader<T> implements RowReader<T> {
|
|||
|
||||
public StandardRowReader(
|
||||
List<DomainResultAssembler<?>> resultAssemblers,
|
||||
List<Initializer> initializers,
|
||||
InitializersList initializers,
|
||||
RowTransformer<T> rowTransformer,
|
||||
Class<T> domainResultJavaType) {
|
||||
this.resultAssemblers = resultAssemblers;
|
||||
|
@ -72,7 +70,13 @@ public class StandardRowReader<T> implements RowReader<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public List<Initializer> getInitializers() {
|
||||
return initializers.asList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InitializersList getInitializersList() {
|
||||
return initializers;
|
||||
}
|
||||
|
||||
|
@ -97,54 +101,20 @@ public class StandardRowReader<T> implements RowReader<T> {
|
|||
|
||||
private void afterRow(RowProcessingState rowProcessingState) {
|
||||
LoadingLogger.LOGGER.trace( "StandardRowReader#afterRow" );
|
||||
|
||||
initializers.forEach( initializer -> initializer.finishUpRow( rowProcessingState ) );
|
||||
initializers.finishUpRow( rowProcessingState );
|
||||
}
|
||||
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
private void coordinateInitializers(RowProcessingState rowProcessingState) {
|
||||
|
||||
final int numberOfInitializers = initializers.size();
|
||||
|
||||
for ( int i = 0; i < numberOfInitializers; i++ ) {
|
||||
final Initializer initializer = initializers.get( i );
|
||||
if ( ! initializer.isCollectionInitializer() ) {
|
||||
initializer.resolveKey( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < numberOfInitializers; i++ ) {
|
||||
final Initializer initializer = initializers.get( i );
|
||||
if ( initializer.isCollectionInitializer() ) {
|
||||
initializer.resolveKey( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < numberOfInitializers; i++ ) {
|
||||
Initializer initializer = initializers.get( i );
|
||||
if ( !( initializer instanceof EntityDelayedFetchInitializer ) && ! (initializer instanceof EntitySelectFetchInitializer ) ) {
|
||||
initializer.resolveInstance( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < numberOfInitializers; i++ ) {
|
||||
Initializer initializer = initializers.get( i );
|
||||
if ( initializer instanceof EntityDelayedFetchInitializer || initializer instanceof EntitySelectFetchInitializer ) {
|
||||
initializer.resolveInstance( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < numberOfInitializers; i++ ) {
|
||||
initializers.get( i ).initializeInstance( rowProcessingState );
|
||||
}
|
||||
initializers.resolveKeys( rowProcessingState );
|
||||
initializers.resolveInstances( rowProcessingState );
|
||||
initializers.initializeInstance( rowProcessingState );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
public void finishUp(JdbcValuesSourceProcessingState processingState) {
|
||||
for ( int i = 0; i < initializers.size(); i++ ) {
|
||||
initializers.get( i ).endLoading( processingState.getExecutionContext() );
|
||||
}
|
||||
initializers.endLoading( processingState.getExecutionContext() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -172,7 +172,7 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
|
|||
}
|
||||
|
||||
if ( this.uniqueSemantic == UniqueSemantic.FILTER
|
||||
|| this.uniqueSemantic == UniqueSemantic.ASSERT && rowProcessingState.hasCollectionInitializers
|
||||
|| this.uniqueSemantic == UniqueSemantic.ASSERT && rowProcessingState.hasCollectionInitializers()
|
||||
|| this.uniqueSemantic == UniqueSemantic.ALLOW && isEnityResultType ) {
|
||||
while ( rowProcessingState.next() ) {
|
||||
results.addUnique( rowReader.readRow( rowProcessingState, processingOptions ) );
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.internal.InitializersList;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState;
|
||||
|
@ -50,7 +51,9 @@ public interface RowReader<R> {
|
|||
* The initializers associated with this reader.
|
||||
*
|
||||
* @see org.hibernate.sql.results.graph.DomainResult
|
||||
* @deprecated use {@link #getInitializersList()}
|
||||
*/
|
||||
@Deprecated
|
||||
List<Initializer> getInitializers();
|
||||
|
||||
/**
|
||||
|
@ -70,4 +73,11 @@ public interface RowReader<R> {
|
|||
@Deprecated
|
||||
RowReaderMemento toMemento(SessionFactoryImplementor factory);
|
||||
|
||||
/**
|
||||
* The initializers associated with this reader.
|
||||
*
|
||||
* @see org.hibernate.sql.results.graph.DomainResult
|
||||
*/
|
||||
InitializersList getInitializersList();
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue