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.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
@ -36,14 +35,14 @@ public final class InitializersList {
|
|||
private final Initializer[] sortedNonCollectionsFirst;
|
||||
private final Initializer[] sortedForResolveInstance;
|
||||
private final boolean hasCollectionInitializers;
|
||||
private final Map<NavigablePath, Initializer> initializerMap;
|
||||
private final NavigablePathMapToInitializer initializerMap;
|
||||
|
||||
private InitializersList(
|
||||
Initializer[] initializers,
|
||||
Initializer[] sortedNonCollectionsFirst,
|
||||
Initializer[] sortedForResolveInstance,
|
||||
boolean hasCollectionInitializers,
|
||||
Map<NavigablePath, Initializer> initializerMap) {
|
||||
NavigablePathMapToInitializer initializerMap) {
|
||||
this.initializers = initializers;
|
||||
this.sortedNonCollectionsFirst = sortedNonCollectionsFirst;
|
||||
this.sortedForResolveInstance = sortedForResolveInstance;
|
||||
|
@ -123,7 +122,7 @@ public final class InitializersList {
|
|||
&& !(initializer instanceof AbstractBatchEntitySelectFetchInitializer );
|
||||
}
|
||||
|
||||
InitializersList build(final Map<NavigablePath, Initializer> initializerMap) {
|
||||
InitializersList build(final NavigablePathMapToInitializer initializerMap) {
|
||||
final int size = initializers.size();
|
||||
final Initializer[] sortedNonCollectionsFirst = 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;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
|
@ -70,7 +68,8 @@ public class ResultsHelper {
|
|||
JdbcValuesMapping jdbcValuesMapping) {
|
||||
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 List<DomainResultAssembler<?>> assemblers = jdbcValuesMapping.resolveAssemblers(
|
||||
|
@ -133,30 +132,13 @@ public class ResultsHelper {
|
|||
}
|
||||
);
|
||||
|
||||
logInitializers( initializerMap );
|
||||
initializerMap.logInitializers();
|
||||
|
||||
final InitializersList initializersList = initializersBuilder.build( initializerMap );
|
||||
|
||||
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(
|
||||
PersistenceContext persistenceContext,
|
||||
CollectionPersister collectionDescriptor,
|
||||
|
|
Loading…
Reference in New Issue