HHH-17282 Introduce a specialized Map for NavigablePath to Initializer
This commit is contained in:
parent
a71df557d9
commit
dba11edf0e
|
@ -9,7 +9,6 @@ package org.hibernate.sql.results.internal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
@ -36,14 +35,14 @@ public final class InitializersList {
|
||||||
private final Initializer[] sortedNonCollectionsFirst;
|
private final Initializer[] sortedNonCollectionsFirst;
|
||||||
private final Initializer[] sortedForResolveInstance;
|
private final Initializer[] sortedForResolveInstance;
|
||||||
private final boolean hasCollectionInitializers;
|
private final boolean hasCollectionInitializers;
|
||||||
private final Map<NavigablePath, Initializer> initializerMap;
|
private final NavigablePathMapToInitializer initializerMap;
|
||||||
|
|
||||||
private InitializersList(
|
private InitializersList(
|
||||||
Initializer[] initializers,
|
Initializer[] initializers,
|
||||||
Initializer[] sortedNonCollectionsFirst,
|
Initializer[] sortedNonCollectionsFirst,
|
||||||
Initializer[] sortedForResolveInstance,
|
Initializer[] sortedForResolveInstance,
|
||||||
boolean hasCollectionInitializers,
|
boolean hasCollectionInitializers,
|
||||||
Map<NavigablePath, Initializer> initializerMap) {
|
NavigablePathMapToInitializer initializerMap) {
|
||||||
this.initializers = initializers;
|
this.initializers = initializers;
|
||||||
this.sortedNonCollectionsFirst = sortedNonCollectionsFirst;
|
this.sortedNonCollectionsFirst = sortedNonCollectionsFirst;
|
||||||
this.sortedForResolveInstance = sortedForResolveInstance;
|
this.sortedForResolveInstance = sortedForResolveInstance;
|
||||||
|
@ -123,7 +122,7 @@ public final class InitializersList {
|
||||||
&& !(initializer instanceof AbstractBatchEntitySelectFetchInitializer );
|
&& !(initializer instanceof AbstractBatchEntitySelectFetchInitializer );
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializersList build(final Map<NavigablePath, Initializer> initializerMap) {
|
InitializersList build(final NavigablePathMapToInitializer initializerMap) {
|
||||||
final int size = initializers.size();
|
final int size = initializers.size();
|
||||||
final Initializer[] sortedNonCollectionsFirst = new Initializer[size];
|
final Initializer[] sortedNonCollectionsFirst = new Initializer[size];
|
||||||
final Initializer[] sortedForResolveInstance = new Initializer[size];
|
final Initializer[] sortedForResolveInstance = new Initializer[size];
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* 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.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.hibernate.spi.NavigablePath;
|
||||||
|
import org.hibernate.sql.results.ResultsLogger;
|
||||||
|
import org.hibernate.sql.results.graph.Initializer;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is in all practical terms a {@code Map<NavigablePath, Initializer>}
|
||||||
|
* but wrapping an HashMap so to keep the client code readable as we need
|
||||||
|
* to:
|
||||||
|
* a) have a way to log all initializers
|
||||||
|
* b) prevent type pollution from happening on Initializer retrieval
|
||||||
|
* I also consider it good practice to only expose the minimal set of
|
||||||
|
* operations the client actually needs.
|
||||||
|
*/
|
||||||
|
public final class NavigablePathMapToInitializer {
|
||||||
|
|
||||||
|
private HashMap<NavigablePath, InitializerHolder> map = null;
|
||||||
|
|
||||||
|
public Initializer get(final NavigablePath navigablePath) {
|
||||||
|
if ( map != null && navigablePath != null ) {
|
||||||
|
final InitializerHolder h = map.get( navigablePath );
|
||||||
|
if ( h != null ) {
|
||||||
|
return h.initializer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(final NavigablePath navigablePath, final Initializer initializer) {
|
||||||
|
Objects.requireNonNull( navigablePath );
|
||||||
|
Objects.requireNonNull( initializer );
|
||||||
|
if ( map == null ) {
|
||||||
|
map = new HashMap<>();
|
||||||
|
}
|
||||||
|
map.put( navigablePath, new InitializerHolder( initializer ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logInitializers() {
|
||||||
|
ResultsLogger logger = ResultsLogger.RESULTS_MESSAGE_LOGGER;
|
||||||
|
if ( !logger.isDebugEnabled() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( map == null ) {
|
||||||
|
logger.debug( "Initializer list is empty" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//Apparently we want to log this on multiple lines (existing code did this - not sure if that was by design):
|
||||||
|
//using a StringBuilder to avoid potentially interleaving the logs from different operations.
|
||||||
|
final StringBuilder sb = new StringBuilder( "Initializer list:\n" );
|
||||||
|
for ( Map.Entry<NavigablePath, InitializerHolder> holderEntry : map.entrySet() ) {
|
||||||
|
final NavigablePath navigablePath = holderEntry.getKey();
|
||||||
|
final Initializer initializer = holderEntry.getValue().initializer;
|
||||||
|
String formatted = String.format(
|
||||||
|
" %s -> %s@%s (%s)",
|
||||||
|
navigablePath,
|
||||||
|
initializer,
|
||||||
|
initializer.hashCode(),
|
||||||
|
initializer.getInitializedPart()
|
||||||
|
);
|
||||||
|
sb.append( '\t' );
|
||||||
|
sb.append( formatted );
|
||||||
|
sb.append( '\n' );
|
||||||
|
}
|
||||||
|
logger.debug( sb.toString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Custom holder to avoid type pollution:
|
||||||
|
//we make the type explicit, and this is a concrete class.
|
||||||
|
private static final class InitializerHolder {
|
||||||
|
final Initializer initializer;
|
||||||
|
|
||||||
|
private InitializerHolder(final Initializer init) {
|
||||||
|
this.initializer = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,9 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.results.internal;
|
package org.hibernate.sql.results.internal;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
|
@ -70,7 +68,8 @@ public class ResultsHelper {
|
||||||
JdbcValuesMapping jdbcValuesMapping) {
|
JdbcValuesMapping jdbcValuesMapping) {
|
||||||
final SessionFactoryImplementor sessionFactory = executionContext.getSession().getFactory();
|
final SessionFactoryImplementor sessionFactory = executionContext.getSession().getFactory();
|
||||||
|
|
||||||
final Map<NavigablePath, Initializer> initializerMap = new LinkedHashMap<>();
|
//custom Map<NavigablePath, Initializer>
|
||||||
|
final NavigablePathMapToInitializer initializerMap = new NavigablePathMapToInitializer();
|
||||||
final InitializersList.Builder initializersBuilder = new InitializersList.Builder();
|
final InitializersList.Builder initializersBuilder = new InitializersList.Builder();
|
||||||
|
|
||||||
final List<DomainResultAssembler<?>> assemblers = jdbcValuesMapping.resolveAssemblers(
|
final List<DomainResultAssembler<?>> assemblers = jdbcValuesMapping.resolveAssemblers(
|
||||||
|
@ -133,30 +132,13 @@ public class ResultsHelper {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
logInitializers( initializerMap );
|
initializerMap.logInitializers();
|
||||||
|
|
||||||
final InitializersList initializersList = initializersBuilder.build( initializerMap );
|
final InitializersList initializersList = initializersBuilder.build( initializerMap );
|
||||||
|
|
||||||
return new StandardRowReader<>( assemblers, initializersList, rowTransformer, transformedResultJavaType );
|
return new StandardRowReader<>( assemblers, initializersList, rowTransformer, transformedResultJavaType );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void logInitializers(Map<NavigablePath, Initializer> initializerMap) {
|
|
||||||
if ( ! ResultsLogger.RESULTS_MESSAGE_LOGGER.isDebugEnabled() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultsLogger.RESULTS_MESSAGE_LOGGER.debug( "Initializer list" );
|
|
||||||
initializerMap.forEach( (navigablePath, initializer) -> {
|
|
||||||
ResultsLogger.RESULTS_MESSAGE_LOGGER.debugf(
|
|
||||||
" %s -> %s@%s (%s)",
|
|
||||||
navigablePath,
|
|
||||||
initializer,
|
|
||||||
initializer.hashCode(),
|
|
||||||
initializer.getInitializedPart()
|
|
||||||
);
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void finalizeCollectionLoading(
|
public static void finalizeCollectionLoading(
|
||||||
PersistenceContext persistenceContext,
|
PersistenceContext persistenceContext,
|
||||||
CollectionPersister collectionDescriptor,
|
CollectionPersister collectionDescriptor,
|
||||||
|
|
Loading…
Reference in New Issue