Implemented SelectEagerCollectionInitializer

This commit is contained in:
Andrea Boriero 2020-03-09 18:04:31 +00:00
parent 2fa3889e5a
commit 6462218587
38 changed files with 443 additions and 480 deletions

View File

@ -73,12 +73,8 @@ public abstract class AbstractBagSemantics<B extends Collection<?>> implements C
String resultVariable, String resultVariable,
LockMode lockMode, LockMode lockMode,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
final TableGroup tableGroup = creationState.getSqlAstCreationState()
.getFromClauseAccess()
.getTableGroup( navigablePath );
return new BagInitializerProducer( return new BagInitializerProducer(
attributeMapping, attributeMapping,
selected,
attributeMapping.getIdentifierDescriptor() == null ? null : attributeMapping.getIdentifierDescriptor().generateFetch( attributeMapping.getIdentifierDescriptor() == null ? null : attributeMapping.getIdentifierDescriptor().generateFetch(
fetchParent, fetchParent,
navigablePath.append( CollectionPart.Nature.ID.getName() ), navigablePath.append( CollectionPart.Nature.ID.getName() ),

View File

@ -86,12 +86,8 @@ public abstract class AbstractMapSemantics<M extends Map<?,?>> implements MapSem
String resultVariable, String resultVariable,
LockMode lockMode, LockMode lockMode,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
final TableGroup tableGroup = creationState.getSqlAstCreationState()
.getFromClauseAccess()
.getTableGroup( navigablePath );
return new MapInitializerProducer( return new MapInitializerProducer(
attributeMapping, attributeMapping,
selected,
attributeMapping.getIndexDescriptor().generateFetch( attributeMapping.getIndexDescriptor().generateFetch(
fetchParent, fetchParent,
navigablePath.append( CollectionPart.Nature.INDEX.getName() ), navigablePath.append( CollectionPart.Nature.INDEX.getName() ),

View File

@ -58,7 +58,6 @@ public abstract class AbstractSetSemantics<S extends Set<?>> implements Collecti
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
return new SetInitializerProducer( return new SetInitializerProducer(
attributeMapping, attributeMapping,
selected,
attributeMapping.getElementDescriptor().generateFetch( attributeMapping.getElementDescriptor().generateFetch(
fetchParent, fetchParent,
navigablePath.append( CollectionPart.Nature.ELEMENT.getName() ), navigablePath.append( CollectionPart.Nature.ELEMENT.getName() ),

View File

@ -133,6 +133,7 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
public void initializeEmptyCollection(CollectionPersister persister) { public void initializeEmptyCollection(CollectionPersister persister) {
assert array == null; assert array == null;
array = Array.newInstance( persister.getElementClass(), 0 ); array = Array.newInstance( persister.getElementClass(), 0 );
persister.getAttributeMapping().getPropertyAccess().getSetter().set( getOwner(), array, getSession().getFactory() );
endRead(); endRead();
} }

View File

@ -104,12 +104,8 @@ public class StandardArraySemantics implements CollectionSemantics<Object[]> {
String resultVariable, String resultVariable,
LockMode lockMode, LockMode lockMode,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
final TableGroup tableGroup = creationState.getSqlAstCreationState()
.getFromClauseAccess()
.getTableGroup( navigablePath );
return new ArrayInitializerProducer( return new ArrayInitializerProducer(
attributeMapping, attributeMapping,
selected,
attributeMapping.getIndexDescriptor().generateFetch( attributeMapping.getIndexDescriptor().generateFetch(
fetchParent, fetchParent,
navigablePath.append( CollectionPart.Nature.INDEX.getName() ), navigablePath.append( CollectionPart.Nature.INDEX.getName() ),

View File

@ -78,12 +78,8 @@ public class StandardListSemantics implements CollectionSemantics<List> {
String resultVariable, String resultVariable,
LockMode lockMode, LockMode lockMode,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
final TableGroup tableGroup = creationState.getSqlAstCreationState()
.getFromClauseAccess()
.getTableGroup( navigablePath );
return new ListInitializerProducer( return new ListInitializerProducer(
attributeMapping, attributeMapping,
selected,
attributeMapping.getIndexDescriptor().generateFetch( attributeMapping.getIndexDescriptor().generateFetch(
fetchParent, fetchParent,
navigablePath.append( CollectionPart.Nature.INDEX.getName() ), navigablePath.append( CollectionPart.Nature.INDEX.getName() ),

View File

@ -90,7 +90,8 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
private void handlePotentiallyEmptyCollection( private void handlePotentiallyEmptyCollection(
PersistentCollection collection, PersistentCollection collection,
SessionImplementor source, SessionImplementor source,
CollectionEntry ce, CollectionPersister ceLoadedPersister) { CollectionEntry ce,
CollectionPersister ceLoadedPersister) {
if ( !collection.wasInitialized() ) { if ( !collection.wasInitialized() ) {
collection.initializeEmptyCollection( ceLoadedPersister ); collection.initializeEmptyCollection( ceLoadedPersister );
org.hibernate.sql.results.internal.Helper.finalizeCollectionLoading( org.hibernate.sql.results.internal.Helper.finalizeCollectionLoading(

View File

@ -56,6 +56,7 @@ import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.collection.internal.CollectionDomainResult; import org.hibernate.sql.results.graph.collection.internal.CollectionDomainResult;
import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch; import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch;
import org.hibernate.sql.results.graph.collection.internal.EagerCollectionFetch; import org.hibernate.sql.results.graph.collection.internal.EagerCollectionFetch;
import org.hibernate.sql.results.graph.collection.internal.SelectEagerCollectionFetch;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.ForeignKeyDirection; import org.hibernate.type.ForeignKeyDirection;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -364,45 +365,55 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
if ( fetchTiming == FetchTiming.IMMEDIATE || selected || getCollectionDescriptor().getCollectionType().hasHolder() ) { if ( fetchTiming == FetchTiming.IMMEDIATE) {
final TableGroup collectionTableGroup = sqlAstCreationState.getFromClauseAccess().resolveTableGroup( if ( selected ) {
fetchablePath, final TableGroup collectionTableGroup = sqlAstCreationState.getFromClauseAccess().resolveTableGroup(
p -> { fetchablePath,
final TableGroup lhsTableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup( fetchParent.getNavigablePath() ); p -> {
final TableGroupJoin tableGroupJoin = createTableGroupJoin( final TableGroup lhsTableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup(
fetchablePath, fetchParent.getNavigablePath() );
lhsTableGroup, final TableGroupJoin tableGroupJoin = createTableGroupJoin(
null, fetchablePath,
SqlAstJoinType.LEFT, lhsTableGroup,
lockMode, null,
creationState.getSqlAliasBaseManager(), SqlAstJoinType.LEFT,
creationState.getSqlAstCreationState().getSqlExpressionResolver(), lockMode,
creationState.getSqlAstCreationState().getCreationContext() creationState.getSqlAliasBaseManager(),
); creationState.getSqlAstCreationState().getSqlExpressionResolver(),
creationState.getSqlAstCreationState().getCreationContext()
);
lhsTableGroup.addTableGroupJoin( tableGroupJoin ); lhsTableGroup.addTableGroupJoin( tableGroupJoin );
sqlAstCreationState.getFromClauseAccess().registerTableGroup( fetchablePath, tableGroupJoin.getJoinedGroup() ); sqlAstCreationState.getFromClauseAccess().registerTableGroup(
fetchablePath,
tableGroupJoin.getJoinedGroup()
);
return tableGroupJoin.getJoinedGroup(); return tableGroupJoin.getJoinedGroup();
} }
); );
return new EagerCollectionFetch( return new EagerCollectionFetch(
fetchablePath, fetchablePath,
this, this,
collectionTableGroup, collectionTableGroup,
getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(), fetchParent,
fetchParent, creationState
creationState );
); }
else {
return new SelectEagerCollectionFetch( fetchablePath, this, fetchParent );
}
} }
if ( getCollectionDescriptor().getCollectionType().hasHolder() ) {
return new SelectEagerCollectionFetch( fetchablePath, this, fetchParent );
}
return new DelayedCollectionFetch( return new DelayedCollectionFetch(
fetchablePath, fetchablePath,
this, this,
true,
fetchParent fetchParent
); );
} }

View File

@ -56,11 +56,6 @@ public interface Fetch extends DomainResultGraphNode {
*/ */
boolean hasTableGroup(); boolean hasTableGroup();
/**
* Is this fetch nullable? Meaning is it mapped as being optional?
*/
boolean isNullable();
/** /**
* Create the assembler for this fetch * Create the assembler for this fetch
*/ */

View File

@ -92,11 +92,6 @@ public class BasicFetch<T> implements Fetch, BasicResultGraphNode<T> {
return navigablePath; return navigablePath;
} }
@Override
public boolean isNullable() {
return nullable;
}
@Override @Override
public DomainResultAssembler createAssembler( public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,

View File

@ -0,0 +1,46 @@
/*
* 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.graph.collection.internal;
import org.hibernate.collection.internal.PersistentArrayHolder;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Andrea Boriero
*/
public abstract class AbstractCollectionAssembler implements DomainResultAssembler {
private final PluralAttributeMapping fetchedMapping;
protected final CollectionInitializer initializer;
public AbstractCollectionAssembler(
PluralAttributeMapping fetchedMapping,
CollectionInitializer initializer) {
this.fetchedMapping = fetchedMapping;
this.initializer = initializer;
}
@Override
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
PersistentCollection collectionInstance = initializer.getCollectionInstance();
if ( collectionInstance instanceof PersistentArrayHolder ) {
return collectionInstance.getValue();
}
return collectionInstance;
}
@Override
public JavaTypeDescriptor getAssembledJavaTypeDescriptor() {
return fetchedMapping.getJavaTypeDescriptor();
}
}

View File

@ -6,16 +6,11 @@
*/ */
package org.hibernate.sql.results.graph.collection.internal; package org.hibernate.sql.results.graph.collection.internal;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.sql.results.graph.collection.CollectionLoadingLogger;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
@ -26,42 +21,44 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
*/ */
public abstract class AbstractCollectionInitializer implements CollectionInitializer { public abstract class AbstractCollectionInitializer implements CollectionInitializer {
private final NavigablePath collectionPath; private final NavigablePath collectionPath;
private final PluralAttributeMapping collectionAttributeMapping; protected final PluralAttributeMapping collectionAttributeMapping;
private final FetchParentAccess parentAccess; protected final FetchParentAccess parentAccess;
private final boolean selected; protected PersistentCollection collectionInstance;
protected CollectionKey collectionKey;
/**
* refers to the collection's container value - which collection-key?
*/
private final DomainResultAssembler keyContainerAssembler;
/**
* refers to the rows entry in the collection. null indicates that the collection is empty
*/
private final DomainResultAssembler keyCollectionAssembler;
// per-row state
private Object keyContainerValue;
private Object keyCollectionValue;
private CollectionKey collectionKey;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected AbstractCollectionInitializer( protected AbstractCollectionInitializer(
NavigablePath collectionPath, NavigablePath collectionPath,
PluralAttributeMapping collectionAttributeMapping, PluralAttributeMapping collectionAttributeMapping,
FetchParentAccess parentAccess, FetchParentAccess parentAccess) {
boolean selected,
DomainResultAssembler keyContainerAssembler,
DomainResultAssembler keyCollectionAssembler) {
this.collectionPath = collectionPath; this.collectionPath = collectionPath;
this.collectionAttributeMapping = collectionAttributeMapping; this.collectionAttributeMapping = collectionAttributeMapping;
this.parentAccess = parentAccess; this.parentAccess = parentAccess;
this.selected = selected; }
this.keyContainerAssembler = keyContainerAssembler;
this.keyCollectionAssembler = keyCollectionAssembler; @Override
public void resolveKey(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
// already resolved
return;
}
final Object parentKey = parentAccess.getParentKey();
if ( parentKey != null ) {
collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
parentKey
);
parentAccess.registerResolutionListener( owner -> collectionInstance.setOwner( owner ) );
}
}
@Override
public PersistentCollection getCollectionInstance() {
return collectionInstance;
} }
@Override @Override
@ -78,119 +75,18 @@ public abstract class AbstractCollectionInitializer implements CollectionInitial
return getCollectionAttributeMapping(); return getCollectionAttributeMapping();
} }
/**
* Are the values for performing this initialization present in the current
* {@link JdbcValuesSourceProcessingState}?
* Or should a separate/subsequent select be performed
*
* todo (6.0) : opportunity for performance gain by batching these selects triggered at the end of processing the JdbcValuesSource
*/
protected boolean isSelected() {
return selected;
}
protected FetchParentAccess getParentAccess() { protected FetchParentAccess getParentAccess() {
return parentAccess; return parentAccess;
} }
/**
* The value of the container/owner side of the collection key (FK). Identifies the
* owner of the collection
*/
@SuppressWarnings("WeakerAccess")
protected Object getKeyContainerValue() {
return keyContainerValue;
}
/**
* The value of the collection side of the collection key (FK). Identifies
* inclusion in the collection. Can be null to indicate that the current row
* does not contain any collection values
*/
@SuppressWarnings("WeakerAccess")
protected Object getKeyCollectionValue() {
return keyCollectionValue;
}
@Override @Override
public CollectionKey resolveCollectionKey(RowProcessingState rowProcessingState) { public CollectionKey resolveCollectionKey(RowProcessingState rowProcessingState) {
resolveKey( rowProcessingState ); resolveKey( rowProcessingState );
return collectionKey; return collectionKey;
} }
@Override
public void resolveKey(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
// already resolved
return;
}
final CollectionKey loadingKey = rowProcessingState.getCollectionKey();
if ( loadingKey != null ) {
collectionKey = loadingKey;
return;
}
final JdbcValuesSourceProcessingOptions processingOptions = rowProcessingState.getJdbcValuesSourceProcessingState()
.getProcessingOptions();
keyContainerValue = keyContainerAssembler.assemble(
rowProcessingState,
processingOptions
);
if ( keyCollectionAssembler == null || keyContainerAssembler == keyCollectionAssembler ) {
keyCollectionValue = keyContainerValue;
}
else {
keyCollectionValue = keyCollectionAssembler.assemble(
rowProcessingState,
processingOptions
);
}
Object keyContainerValue = getKeyContainerValue();
if ( keyContainerValue != null ) {
this.collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
keyContainerValue
);
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Current row collection key : %s",
StringHelper.collapse( this.getClass().getName() ),
LoggingHelper.toLoggableString( getNavigablePath(), this.collectionKey.getKey() )
);
}
}
else if ( keyCollectionValue != null ) {
this.collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
keyCollectionValue
);
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Current row collection key : %s",
StringHelper.collapse( this.getClass().getName() ),
LoggingHelper.toLoggableString( getNavigablePath(), this.collectionKey.getKey() )
);
}
}
else {
this.collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
parentAccess.getParentKey()
);
}
}
@Override @Override
public void finishUpRow(RowProcessingState rowProcessingState) { public void finishUpRow(RowProcessingState rowProcessingState) {
keyContainerValue = null;
keyCollectionValue = null;
collectionKey = null; collectionKey = null;
} }
} }

View File

@ -24,6 +24,7 @@ import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.collection.CollectionLoadingLogger; import org.hibernate.sql.results.graph.collection.CollectionLoadingLogger;
import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry; import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry;
import org.hibernate.sql.results.internal.LoadingCollectionEntryImpl; import org.hibernate.sql.results.internal.LoadingCollectionEntryImpl;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
/** /**
@ -40,52 +41,42 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
private final LockMode lockMode; private final LockMode lockMode;
// per-row state // per-row state
private PersistentCollection collectionInstance;
private LoadingCollectionEntryImpl responsibility; private LoadingCollectionEntryImpl responsibility;
private boolean responsible;
/**
* refers to the collection's container value - which collection-key?
*/
private final DomainResultAssembler keyContainerAssembler;
/**
* refers to the rows entry in the collection. null indicates that the collection is empty
*/
private final DomainResultAssembler keyCollectionAssembler;
// per-row state
private Object keyContainerValue;
private Object keyCollectionValue;
public AbstractImmediateCollectionInitializer( public AbstractImmediateCollectionInitializer(
NavigablePath collectionPath, NavigablePath collectionPath,
PluralAttributeMapping collectionAttributeMapping, PluralAttributeMapping collectionAttributeMapping,
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
boolean selected,
LockMode lockMode, LockMode lockMode,
DomainResultAssembler keyContainerAssembler, DomainResultAssembler keyContainerAssembler,
DomainResultAssembler keyCollectionAssembler) { DomainResultAssembler keyCollectionAssembler) {
super( collectionPath, collectionAttributeMapping, parentAccess, selected, keyContainerAssembler, keyCollectionAssembler ); super( collectionPath, collectionAttributeMapping, parentAccess );
this.keyContainerAssembler = keyContainerAssembler;
this.keyCollectionAssembler = keyCollectionAssembler;
this.lockMode = lockMode; this.lockMode = lockMode;
} }
@Override
public PersistentCollection getCollectionInstance() {
return collectionInstance;
}
@Override @Override
public void resolveInstance(RowProcessingState rowProcessingState) { public void resolveInstance(RowProcessingState rowProcessingState) {
if ( collectionInstance != null ) { if ( collectionInstance != null ) {
return; return;
} }
final PluralAttributeMapping collectionAttributeMapping = getCollectionAttributeMapping();
final CollectionPersister collectionDescriptor = collectionAttributeMapping.getCollectionDescriptor();
final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics();
final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final CollectionKey collectionKey = resolveCollectionKey( rowProcessingState );
if ( collectionKey == null ) {
collectionInstance = collectionSemantics.instantiateWrapper(
null,
collectionDescriptor,
session
);
collectionInstance.initializeEmptyCollection( collectionDescriptor );
persistenceContext.addNonLazyCollection( collectionInstance );
}
if ( CollectionLoadingLogger.TRACE_ENABLED ) { if ( CollectionLoadingLogger.TRACE_ENABLED ) {
CollectionLoadingLogger.INSTANCE.tracef( CollectionLoadingLogger.INSTANCE.tracef(
"(%s) Beginning Initializer#resolveInstance for collection : %s", "(%s) Beginning Initializer#resolveInstance for collection : %s",
@ -99,6 +90,8 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// First, look for a LoadingCollectionEntry // First, look for a LoadingCollectionEntry
final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final LoadingCollectionEntry existingLoadingEntry = persistenceContext final LoadingCollectionEntry existingLoadingEntry = persistenceContext
.getLoadContexts() .getLoadContexts()
@ -159,7 +152,6 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
return; return;
} }
else { else {
assert isSelected();
takeResponsibility( rowProcessingState, collectionKey ); takeResponsibility( rowProcessingState, collectionKey );
} }
} }
@ -185,25 +177,16 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
return; return;
} }
else { else {
assert isSelected();
takeResponsibility( rowProcessingState, collectionKey ); takeResponsibility( rowProcessingState, collectionKey );
} }
} }
} }
if ( ! isSelected() ) {
collectionInstance = collectionSemantics.instantiateWrapper(
collectionKey.getKey(),
collectionDescriptor,
session
);
persistenceContext.addNonLazyCollection( collectionInstance );
// EARLY EXIT!!!
return;
}
} }
final PluralAttributeMapping collectionAttributeMapping = getCollectionAttributeMapping();
final CollectionPersister collectionDescriptor = collectionAttributeMapping.getCollectionDescriptor();
final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics();
if ( collectionInstance == null && collectionKey != null ) { if ( collectionInstance == null && collectionKey != null ) {
collectionInstance = collectionSemantics.instantiateWrapper( collectionInstance = collectionSemantics.instantiateWrapper(
collectionKey.getKey(), collectionKey.getKey(),
@ -240,10 +223,6 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
owner -> collectionInstance.setOwner( owner ) owner -> collectionInstance.setOwner( owner )
); );
} }
// if ( getCollectionDescriptor().getSemantics().getCollectionClassification() == CollectionClassification.ARRAY ) {
// persistenceContext.addCollectionHolder( collectionInstance );
// }
} }
} }
@ -260,6 +239,93 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
); );
} }
@Override
public void resolveKey(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
// already resolved
return;
}
final CollectionKey loadingKey = rowProcessingState.getCollectionKey();
if ( loadingKey != null ) {
collectionKey = loadingKey;
return;
}
final JdbcValuesSourceProcessingOptions processingOptions = rowProcessingState.getJdbcValuesSourceProcessingState()
.getProcessingOptions();
keyContainerValue = keyContainerAssembler.assemble(
rowProcessingState,
processingOptions
);
if ( keyCollectionAssembler == null || keyContainerAssembler == keyCollectionAssembler ) {
keyCollectionValue = keyContainerValue;
}
else {
keyCollectionValue = keyCollectionAssembler.assemble(
rowProcessingState,
processingOptions
);
}
Object keyContainerValue = getKeyContainerValue();
if ( keyContainerValue != null ) {
this.collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
keyContainerValue
);
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Current row collection key : %s",
StringHelper.collapse( this.getClass().getName() ),
LoggingHelper.toLoggableString( getNavigablePath(), this.collectionKey.getKey() )
);
}
}
else if ( keyCollectionValue != null ) {
this.collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
keyCollectionValue
);
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Current row collection key : %s",
StringHelper.collapse( this.getClass().getName() ),
LoggingHelper.toLoggableString( getNavigablePath(), this.collectionKey.getKey() )
);
}
}
else {
this.collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
parentAccess.getParentKey()
);
}
}
/**
* The value of the container/owner side of the collection key (FK). Identifies the
* owner of the collection
*/
@SuppressWarnings("WeakerAccess")
protected Object getKeyContainerValue() {
return keyContainerValue;
}
/**
* The value of the collection side of the collection key (FK). Identifies
* inclusion in the collection. Can be null to indicate that the current row
* does not contain any collection values
*/
@SuppressWarnings("WeakerAccess")
protected Object getKeyCollectionValue() {
return keyCollectionValue;
}
@Override @Override
public void initializeInstance(RowProcessingState rowProcessingState) { public void initializeInstance(RowProcessingState rowProcessingState) {
if ( responsibility == null ) { if ( responsibility == null ) {
@ -295,6 +361,8 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
public void finishUpRow(RowProcessingState rowProcessingState) { public void finishUpRow(RowProcessingState rowProcessingState) {
super.finishUpRow( rowProcessingState ); super.finishUpRow( rowProcessingState );
keyContainerValue = null;
keyCollectionValue = null;
collectionInstance = null; collectionInstance = null;
responsibility = null; responsibility = null;
} }

View File

@ -31,7 +31,6 @@ public class ArrayInitializer extends AbstractImmediateCollectionInitializer {
NavigablePath navigablePath, NavigablePath navigablePath,
PluralAttributeMapping arrayDescriptor, PluralAttributeMapping arrayDescriptor,
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
boolean selected,
LockMode lockMode, LockMode lockMode,
DomainResultAssembler keyContainerAssembler, DomainResultAssembler keyContainerAssembler,
DomainResultAssembler keyCollectionAssembler, DomainResultAssembler keyCollectionAssembler,
@ -41,7 +40,6 @@ public class ArrayInitializer extends AbstractImmediateCollectionInitializer {
navigablePath, navigablePath,
arrayDescriptor, arrayDescriptor,
parentAccess, parentAccess,
selected,
lockMode, lockMode,
keyContainerAssembler, keyContainerAssembler,
keyCollectionAssembler keyCollectionAssembler

View File

@ -24,17 +24,14 @@ import org.hibernate.sql.results.graph.Initializer;
*/ */
public class ArrayInitializerProducer implements CollectionInitializerProducer { public class ArrayInitializerProducer implements CollectionInitializerProducer {
private final PluralAttributeMapping arrayDescriptor; private final PluralAttributeMapping arrayDescriptor;
private final boolean joined;
private final Fetch listIndexFetch; private final Fetch listIndexFetch;
private final Fetch elementFetch; private final Fetch elementFetch;
public ArrayInitializerProducer( public ArrayInitializerProducer(
PluralAttributeMapping arrayDescriptor, PluralAttributeMapping arrayDescriptor,
boolean joined,
Fetch listIndexFetch, Fetch listIndexFetch,
Fetch elementFetch) { Fetch elementFetch) {
this.arrayDescriptor = arrayDescriptor; this.arrayDescriptor = arrayDescriptor;
this.joined = joined;
this.listIndexFetch = listIndexFetch; this.listIndexFetch = listIndexFetch;
this.elementFetch = elementFetch; this.elementFetch = elementFetch;
} }
@ -53,7 +50,6 @@ public class ArrayInitializerProducer implements CollectionInitializerProducer {
navigablePath, navigablePath,
arrayDescriptor, arrayDescriptor,
parentAccess, parentAccess,
joined,
lockMode, lockMode,
keyContainerAssembler, keyContainerAssembler,
keyCollectionAssembler, keyCollectionAssembler,

View File

@ -33,13 +33,12 @@ public class BagInitializer extends AbstractImmediateCollectionInitializer {
PluralAttributeMapping bagDescriptor, PluralAttributeMapping bagDescriptor,
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
NavigablePath navigablePath, NavigablePath navigablePath,
boolean selected,
LockMode lockMode, LockMode lockMode,
DomainResultAssembler keyContainerAssembler, DomainResultAssembler keyContainerAssembler,
DomainResultAssembler keyCollectionAssembler, DomainResultAssembler keyCollectionAssembler,
DomainResultAssembler elementAssembler, DomainResultAssembler elementAssembler,
DomainResultAssembler collectionIdAssembler) { DomainResultAssembler collectionIdAssembler) {
super( navigablePath, bagDescriptor, parentAccess, selected, lockMode, keyContainerAssembler, keyCollectionAssembler ); super( navigablePath, bagDescriptor, parentAccess, lockMode, keyContainerAssembler, keyCollectionAssembler );
this.elementAssembler = elementAssembler; this.elementAssembler = elementAssembler;
this.collectionIdAssembler = collectionIdAssembler; this.collectionIdAssembler = collectionIdAssembler;
} }

View File

@ -25,17 +25,14 @@ import org.hibernate.sql.results.graph.Initializer;
*/ */
public class BagInitializerProducer implements CollectionInitializerProducer { public class BagInitializerProducer implements CollectionInitializerProducer {
private final PluralAttributeMapping bagDescriptor; private final PluralAttributeMapping bagDescriptor;
private final boolean selected;
private final Fetch collectionIdFetch; private final Fetch collectionIdFetch;
private final Fetch elementFetch; private final Fetch elementFetch;
public BagInitializerProducer( public BagInitializerProducer(
PluralAttributeMapping bagDescriptor, PluralAttributeMapping bagDescriptor,
boolean selected,
Fetch collectionIdFetch, Fetch collectionIdFetch,
Fetch elementFetch) { Fetch elementFetch) {
this.bagDescriptor = bagDescriptor; this.bagDescriptor = bagDescriptor;
this.selected = selected;
if ( bagDescriptor.getIdentifierDescriptor() != null ) { if ( bagDescriptor.getIdentifierDescriptor() != null ) {
assert collectionIdFetch != null; assert collectionIdFetch != null;
@ -82,7 +79,6 @@ public class BagInitializerProducer implements CollectionInitializerProducer {
bagDescriptor, bagDescriptor,
parentAccess, parentAccess,
navigablePath, navigablePath,
selected,
lockMode, lockMode,
keyContainerAssembler, keyContainerAssembler,
keyCollectionAssembler, keyCollectionAssembler,

View File

@ -18,19 +18,15 @@ public abstract class CollectionFetch implements Fetch {
private final NavigablePath fetchedPath; private final NavigablePath fetchedPath;
private final PluralAttributeMapping fetchedAttribute; private final PluralAttributeMapping fetchedAttribute;
private final boolean nullable;
private final FetchParent fetchParent; private final FetchParent fetchParent;
public CollectionFetch( public CollectionFetch(
NavigablePath fetchedPath, NavigablePath fetchedPath,
PluralAttributeMapping fetchedAttribute, PluralAttributeMapping fetchedAttribute,
boolean nullable,
FetchParent fetchParent) { FetchParent fetchParent) {
this.fetchedPath = fetchedPath; this.fetchedPath = fetchedPath;
this.fetchedAttribute = fetchedAttribute; this.fetchedAttribute = fetchedAttribute;
this.fetchParent = fetchParent; this.fetchParent = fetchParent;
this.nullable = nullable;
} }
@Override @Override
@ -47,9 +43,4 @@ public abstract class CollectionFetch implements Fetch {
public NavigablePath getNavigablePath() { public NavigablePath getNavigablePath() {
return fetchedPath; return fetchedPath;
} }
@Override
public boolean isNullable() {
return nullable;
}
} }

View File

@ -8,50 +8,23 @@ package org.hibernate.sql.results.graph.collection.internal;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.collection.internal.PersistentArrayHolder;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class DelayedCollectionAssembler implements DomainResultAssembler { public class DelayedCollectionAssembler extends AbstractCollectionAssembler {
private final PluralAttributeMapping fetchedMapping;
private final CollectionInitializer initializer;
public DelayedCollectionAssembler( public DelayedCollectionAssembler(
NavigablePath fetchPath, NavigablePath fetchPath,
PluralAttributeMapping fetchedMapping, PluralAttributeMapping fetchedMapping,
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
Consumer<Initializer> collector, Consumer<Initializer> collector,
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
this.fetchedMapping = fetchedMapping; super( fetchedMapping, new DelayedCollectionInitializer( fetchPath, fetchedMapping, parentAccess ) );
this.initializer = new DelayedCollectionInitializer( fetchPath, fetchedMapping, parentAccess );
collector.accept( initializer ); collector.accept( initializer );
} }
@Override
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
PersistentCollection collectionInstance = initializer.getCollectionInstance();
if ( collectionInstance instanceof PersistentArrayHolder ) {
return collectionInstance.getValue();
}
return collectionInstance;
}
@Override
public JavaTypeDescriptor getAssembledJavaTypeDescriptor() {
return fetchedMapping.getJavaTypeDescriptor();
}
} }

View File

@ -25,9 +25,8 @@ public class DelayedCollectionFetch extends CollectionFetch {
public DelayedCollectionFetch( public DelayedCollectionFetch(
NavigablePath fetchedPath, NavigablePath fetchedPath,
PluralAttributeMapping fetchedAttribute, PluralAttributeMapping fetchedAttribute,
boolean nullable,
FetchParent fetchParent) { FetchParent fetchParent) {
super( fetchedPath, fetchedAttribute, nullable, fetchParent ); super( fetchedPath, fetchedAttribute, fetchParent );
} }
@Override @Override

View File

@ -8,94 +8,35 @@ package org.hibernate.sql.results.graph.collection.internal;
import org.hibernate.collection.spi.CollectionSemantics; import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.log.LoggingHelper; import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry; import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry;
import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry;
import org.hibernate.sql.results.graph.entity.EntityInitializer;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class DelayedCollectionInitializer implements CollectionInitializer { public class DelayedCollectionInitializer extends AbstractCollectionInitializer {
private final NavigablePath fetchedPath;
private final PluralAttributeMapping fetchedMapping;
private final FetchParentAccess parentAccess;
private CollectionKey collectionKey;
private PersistentCollection collectionInstance;
public DelayedCollectionInitializer( public DelayedCollectionInitializer(
NavigablePath fetchedPath, NavigablePath fetchedPath,
PluralAttributeMapping fetchedMapping, PluralAttributeMapping fetchedMapping,
FetchParentAccess parentAccess) { FetchParentAccess parentAccess) {
this.fetchedPath = fetchedPath; super( fetchedPath, fetchedMapping, parentAccess );
this.fetchedMapping = fetchedMapping;
this.parentAccess = parentAccess;
}
@Override
public NavigablePath getNavigablePath() {
return fetchedPath;
}
@Override
public void resolveKey(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
// already resolved
return;
}
final Object parentKey = parentAccess.getParentKey();
if ( parentKey != null ) {
collectionKey = new CollectionKey(
fetchedMapping.getCollectionDescriptor(),
parentKey
);
parentAccess.registerResolutionListener( owner -> collectionInstance.setOwner( owner ) );
}
} }
@Override @Override
public void resolveInstance(RowProcessingState rowProcessingState) { public void resolveInstance(RowProcessingState rowProcessingState) {
final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
if ( collectionKey != null ) { if ( collectionKey != null ) {
final SharedSessionContractImplementor session = rowProcessingState.getSession(); final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext(); final PersistenceContext persistenceContext = session.getPersistenceContext();
if ( collectionKey != null ) {
EntityInitializer entityInitializer = getEntityInitializer( rowProcessingState );
final Object entityUsingInterceptor = persistenceContext.getEntity( entityInitializer.getEntityKey() );
if ( entityUsingInterceptor != null ) {
return;
}
final Object key = collectionKey.getKey();
final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts()
.findLoadingCollectionEntry( collectionKey );
final PersistentCollection registeredInstance = persistenceContext.getCollection( collectionKey );
final Object key = collectionKey.getKey();
if ( loadingEntry != null ) {
instance = loadingEntry.getCollectionInstance();
return;
}
final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts() final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts()
.findLoadingCollectionEntry( collectionKey ); .findLoadingCollectionEntry( collectionKey );
@ -104,9 +45,6 @@ public class DelayedCollectionInitializer implements CollectionInitializer {
return; return;
} }
if ( registeredInstance != null ) {
instance = registeredInstance;
return;
final PersistentCollection existing = persistenceContext.getCollection( collectionKey ); final PersistentCollection existing = persistenceContext.getCollection( collectionKey );
if ( existing != null ) { if ( existing != null ) {
@ -114,38 +52,12 @@ public class DelayedCollectionInitializer implements CollectionInitializer {
return; return;
} }
instance = makePersistentCollection( fetchedMapping, key, rowProcessingState ); final CollectionPersister collectionDescriptor = collectionAttributeMapping.getCollectionDescriptor();
persistenceContext.addUninitializedCollection(
getInitializingCollectionDescriptor(),
instance,
key
);
}
else {
instance = makePersistentCollection( fetchedMapping, collectionKey, rowProcessingState );
instance.initializeEmptyCollection( getInitializingCollectionDescriptor() );
persistenceContext.addNonLazyCollection( instance );
}
}
private static PersistentCollection makePersistentCollection(
PluralAttributeMapping fetchedMapping,
Object collectionKey,
RowProcessingState rowProcessingState) {
final CollectionPersister collectionDescriptor = fetchedMapping.getCollectionDescriptor();
final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics();
final CollectionPersister collectionDescriptor = fetchedMapping.getCollectionDescriptor();
final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics(); final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics();
return collectionSemantics.instantiateWrapper( final Object key = collectionKey.getKey();
collectionKey,
collectionDescriptor,
rowProcessingState.getSession()
);
}
collectionInstance = collectionSemantics.instantiateWrapper( collectionInstance = collectionSemantics.instantiateWrapper(
key, key,
collectionDescriptor, collectionDescriptor,
@ -162,19 +74,12 @@ public class DelayedCollectionInitializer implements CollectionInitializer {
key key
); );
private EntityInitializer getEntityInitializer(RowProcessingState rowProcessingState) {
Initializer initializer = rowProcessingState.resolveInitializer( getNavigablePath().getParent() );
while ( !( initializer instanceof EntityInitializer ) ) {
initializer = rowProcessingState.resolveInitializer( initializer.getNavigablePath().getParent() );
if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ARRAY ) { if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ARRAY ) {
session.getPersistenceContext().addCollectionHolder( collectionInstance ); session.getPersistenceContext().addCollectionHolder( collectionInstance );
} }
} }
return (EntityInitializer) initializer;
} }
@Override @Override
public void initializeInstance(RowProcessingState rowProcessingState) { public void initializeInstance(RowProcessingState rowProcessingState) {
} }
@ -186,23 +91,7 @@ public class DelayedCollectionInitializer implements CollectionInitializer {
@Override @Override
public void finishUpRow(RowProcessingState rowProcessingState) { public void finishUpRow(RowProcessingState rowProcessingState) {
collectionKey = null; super.finishUpRow( rowProcessingState );
instance = null; collectionInstance = null;
}
@Override
public PluralAttributeMapping getInitializedPart() {
return fetchedMapping;
}
@Override
public PersistentCollection getCollectionInstance() {
return instance;
}
@Override
public CollectionKey resolveCollectionKey(RowProcessingState rowProcessingState) {
resolveKey( rowProcessingState );
return collectionKey;
} }
} }

View File

@ -6,41 +6,17 @@
*/ */
package org.hibernate.sql.results.graph.collection.internal; package org.hibernate.sql.results.graph.collection.internal;
import org.hibernate.collection.internal.PersistentArrayHolder;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EagerCollectionAssembler implements DomainResultAssembler { public class EagerCollectionAssembler extends AbstractCollectionAssembler {
private final PluralAttributeMapping fetchedMapping;
private final CollectionInitializer initializer;
public EagerCollectionAssembler( public EagerCollectionAssembler(
PluralAttributeMapping fetchedMapping, PluralAttributeMapping fetchedMapping,
CollectionInitializer initializer) { CollectionInitializer initializer) {
this.fetchedMapping = fetchedMapping; super( fetchedMapping, initializer );
this.initializer = initializer;
} }
@Override
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
PersistentCollection collectionInstance = initializer.getCollectionInstance();
if ( collectionInstance instanceof PersistentArrayHolder ) {
return collectionInstance.getValue();
}
return collectionInstance;
}
@Override
public JavaTypeDescriptor getAssembledJavaTypeDescriptor() {
return fetchedMapping.getJavaTypeDescriptor();
}
} }

View File

@ -49,10 +49,9 @@ public class EagerCollectionFetch extends CollectionFetch implements FetchParent
NavigablePath fetchedPath, NavigablePath fetchedPath,
PluralAttributeMapping fetchedAttribute, PluralAttributeMapping fetchedAttribute,
TableGroup collectionTableGroup, TableGroup collectionTableGroup,
boolean nullable,
FetchParent fetchParent, FetchParent fetchParent,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
super( fetchedPath, fetchedAttribute, nullable, fetchParent ); super( fetchedPath, fetchedAttribute, fetchParent );
final FromClauseAccess fromClauseAccess = creationState.getSqlAstCreationState().getFromClauseAccess(); final FromClauseAccess fromClauseAccess = creationState.getSqlAstCreationState().getFromClauseAccess();
final NavigablePath parentPath = fetchedPath.getParent(); final NavigablePath parentPath = fetchedPath.getParent();
@ -91,7 +90,7 @@ public class EagerCollectionFetch extends CollectionFetch implements FetchParent
fetchedPath, fetchedPath,
fetchedAttribute, fetchedAttribute,
fetchParent, fetchParent,
nullable, true,
null, null,
// todo (6.0) : we need to propagate these lock modes // todo (6.0) : we need to propagate these lock modes
LockMode.READ, LockMode.READ,

View File

@ -33,13 +33,12 @@ public class ListInitializer extends AbstractImmediateCollectionInitializer {
NavigablePath navigablePath, NavigablePath navigablePath,
PluralAttributeMapping attributeMapping, PluralAttributeMapping attributeMapping,
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
boolean selected,
LockMode lockMode, LockMode lockMode,
DomainResultAssembler keyContainerAssembler, DomainResultAssembler keyContainerAssembler,
DomainResultAssembler keyCollectionAssembler, DomainResultAssembler keyCollectionAssembler,
DomainResultAssembler listIndexAssembler, DomainResultAssembler listIndexAssembler,
DomainResultAssembler elementAssembler) { DomainResultAssembler elementAssembler) {
super( navigablePath, attributeMapping, parentAccess, selected, lockMode, keyContainerAssembler, keyCollectionAssembler ); super( navigablePath, attributeMapping, parentAccess, lockMode, keyContainerAssembler, keyCollectionAssembler );
this.listIndexAssembler = listIndexAssembler; this.listIndexAssembler = listIndexAssembler;
this.elementAssembler = elementAssembler; this.elementAssembler = elementAssembler;

View File

@ -24,17 +24,14 @@ import org.hibernate.sql.results.graph.Initializer;
*/ */
public class ListInitializerProducer implements CollectionInitializerProducer { public class ListInitializerProducer implements CollectionInitializerProducer {
private final PluralAttributeMapping attributeMapping; private final PluralAttributeMapping attributeMapping;
private final boolean joined;
private final Fetch listIndexFetch; private final Fetch listIndexFetch;
private final Fetch elementFetch; private final Fetch elementFetch;
public ListInitializerProducer( public ListInitializerProducer(
PluralAttributeMapping attributeMapping, PluralAttributeMapping attributeMapping,
boolean joined,
Fetch listIndexFetch, Fetch listIndexFetch,
Fetch elementFetch) { Fetch elementFetch) {
this.attributeMapping = attributeMapping; this.attributeMapping = attributeMapping;
this.joined = joined;
this.listIndexFetch = listIndexFetch; this.listIndexFetch = listIndexFetch;
this.elementFetch = elementFetch; this.elementFetch = elementFetch;
} }
@ -53,7 +50,6 @@ public class ListInitializerProducer implements CollectionInitializerProducer {
navigablePath, navigablePath,
attributeMapping, attributeMapping,
parentAccess, parentAccess,
joined,
lockMode, lockMode,
keyContainerAssembler, keyContainerAssembler,
keyCollectionAssembler, keyCollectionAssembler,

View File

@ -34,13 +34,12 @@ public class MapInitializer extends AbstractImmediateCollectionInitializer {
NavigablePath navigablePath, NavigablePath navigablePath,
PluralAttributeMapping attributeMapping, PluralAttributeMapping attributeMapping,
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
boolean selected,
LockMode lockMode, LockMode lockMode,
DomainResultAssembler keyContainerAssembler, DomainResultAssembler keyContainerAssembler,
DomainResultAssembler keyCollectionAssembler, DomainResultAssembler keyCollectionAssembler,
DomainResultAssembler mapKeyAssembler, DomainResultAssembler mapKeyAssembler,
DomainResultAssembler mapValueAssembler) { DomainResultAssembler mapValueAssembler) {
super( navigablePath, attributeMapping, parentAccess, selected, lockMode, keyContainerAssembler, keyCollectionAssembler ); super( navigablePath, attributeMapping, parentAccess, lockMode, keyContainerAssembler, keyCollectionAssembler );
this.mapKeyAssembler = mapKeyAssembler; this.mapKeyAssembler = mapKeyAssembler;
this.mapValueAssembler = mapValueAssembler; this.mapValueAssembler = mapValueAssembler;
} }

View File

@ -24,17 +24,14 @@ import org.hibernate.sql.results.graph.Initializer;
*/ */
public class MapInitializerProducer implements CollectionInitializerProducer { public class MapInitializerProducer implements CollectionInitializerProducer {
private final PluralAttributeMapping mapDescriptor; private final PluralAttributeMapping mapDescriptor;
private final boolean isJoined;
private final Fetch mapKeyFetch; private final Fetch mapKeyFetch;
private final Fetch mapValueFetch; private final Fetch mapValueFetch;
public MapInitializerProducer( public MapInitializerProducer(
PluralAttributeMapping mapDescriptor, PluralAttributeMapping mapDescriptor,
boolean isJoined,
Fetch mapKeyFetch, Fetch mapKeyFetch,
Fetch mapValueFetch) { Fetch mapValueFetch) {
this.mapDescriptor = mapDescriptor; this.mapDescriptor = mapDescriptor;
this.isJoined = isJoined;
this.mapKeyFetch = mapKeyFetch; this.mapKeyFetch = mapKeyFetch;
this.mapValueFetch = mapValueFetch; this.mapValueFetch = mapValueFetch;
} }
@ -65,7 +62,6 @@ public class MapInitializerProducer implements CollectionInitializerProducer {
navigablePath, navigablePath,
mapDescriptor, mapDescriptor,
parentAccess, parentAccess,
isJoined,
lockMode, lockMode,
keyContainerAssembler, keyContainerAssembler,
keyCollectionAssembler, keyCollectionAssembler,

View File

@ -0,0 +1,31 @@
/*
* 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.graph.collection.internal;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.Initializer;
/**
* @author Andrea Boriero
*/
public class SelectEagerCollectionAssembler extends AbstractCollectionAssembler {
public SelectEagerCollectionAssembler(
NavigablePath fetchPath,
PluralAttributeMapping fetchedMapping,
FetchParentAccess parentAccess,
Consumer<Initializer> collector,
AssemblerCreationState creationState) {
super( fetchedMapping, new SelectEagerCollectionInitializer( fetchPath, fetchedMapping, parentAccess ) );
collector.accept( initializer );
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.graph.collection.internal;
import java.util.function.Consumer;
import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Andrea Boriero
*/
public class SelectEagerCollectionFetch extends CollectionFetch {
public SelectEagerCollectionFetch(
NavigablePath fetchedPath,
PluralAttributeMapping fetchedAttribute,
FetchParent fetchParent) {
super( fetchedPath, fetchedAttribute, fetchParent );
}
@Override
public FetchTiming getTiming() {
return FetchTiming.DELAYED;
}
@Override
public boolean hasTableGroup() {
return false;
}
@Override
public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess, Consumer<Initializer> collector, AssemblerCreationState creationState) {
return new SelectEagerCollectionAssembler(
getNavigablePath(),
getFetchedMapping(),
parentAccess,
collector,
creationState
);
}
@Override
public JavaTypeDescriptor getResultJavaTypeDescriptor() {
return getFetchedMapping().getJavaTypeDescriptor();
}
}

View File

@ -0,0 +1,99 @@
/*
* 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.graph.collection.internal;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
/**
* @author Andrea Boriero
*/
public class SelectEagerCollectionInitializer extends AbstractCollectionInitializer {
public SelectEagerCollectionInitializer(
NavigablePath fetchedPath,
PluralAttributeMapping fetchedMapping,
FetchParentAccess parentAccess) {
super( fetchedPath, fetchedMapping, parentAccess );
}
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts()
.findLoadingCollectionEntry( collectionKey );
if ( loadingEntry != null ) {
collectionInstance = loadingEntry.getCollectionInstance();
return;
}
final PersistentCollection existing = persistenceContext.getCollection( collectionKey );
if ( existing != null ) {
collectionInstance = existing;
return;
}
final CollectionPersister collectionDescriptor = collectionAttributeMapping.getCollectionDescriptor();
final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics();
final Object key = collectionKey.getKey();
collectionInstance = collectionSemantics.instantiateWrapper(
key,
collectionDescriptor,
session
);
parentAccess.registerResolutionListener(
owner -> collectionInstance.setOwner( owner )
);
persistenceContext.addUninitializedCollection(
collectionDescriptor,
collectionInstance,
key
);
persistenceContext.addNonLazyCollection( collectionInstance );
if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ARRAY ) {
session.getPersistenceContext().addCollectionHolder( collectionInstance );
}
}
}
@Override
public void initializeInstance(RowProcessingState rowProcessingState) {
}
@Override
public String toString() {
return "SelectEagerCollectionInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")";
}
@Override
public void finishUpRow(RowProcessingState rowProcessingState) {
super.finishUpRow( rowProcessingState );
collectionInstance = null;
}
}

View File

@ -28,12 +28,11 @@ public class SetInitializer extends AbstractImmediateCollectionInitializer {
NavigablePath navigablePath, NavigablePath navigablePath,
PluralAttributeMapping setDescriptor, PluralAttributeMapping setDescriptor,
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
boolean selected,
LockMode lockMode, LockMode lockMode,
DomainResultAssembler keyContainerAssembler, DomainResultAssembler keyContainerAssembler,
DomainResultAssembler keyCollectionAssembler, DomainResultAssembler keyCollectionAssembler,
DomainResultAssembler elementAssembler) { DomainResultAssembler elementAssembler) {
super( navigablePath, setDescriptor, parentAccess, selected, lockMode, keyContainerAssembler, keyCollectionAssembler ); super( navigablePath, setDescriptor, parentAccess, lockMode, keyContainerAssembler, keyCollectionAssembler );
this.elementAssembler = elementAssembler; this.elementAssembler = elementAssembler;
} }

View File

@ -24,16 +24,13 @@ import org.hibernate.sql.results.graph.Initializer;
*/ */
public class SetInitializerProducer implements CollectionInitializerProducer { public class SetInitializerProducer implements CollectionInitializerProducer {
private final PluralAttributeMapping setDescriptor; private final PluralAttributeMapping setDescriptor;
private final boolean isSelected;
private final Fetch elementFetch; private final Fetch elementFetch;
public SetInitializerProducer( public SetInitializerProducer(
PluralAttributeMapping setDescriptor, PluralAttributeMapping setDescriptor,
boolean isSelected,
Fetch elementFetch) { Fetch elementFetch) {
this.setDescriptor = setDescriptor; this.setDescriptor = setDescriptor;
this.elementFetch = elementFetch; this.elementFetch = elementFetch;
this.isSelected = isSelected;
} }
@Override @Override
@ -56,7 +53,6 @@ public class SetInitializerProducer implements CollectionInitializerProducer {
navigablePath, navigablePath,
setDescriptor, setDescriptor,
parentAccess, parentAccess,
isSelected,
lockMode, lockMode,
keyContainerAssembler, keyContainerAssembler,
keyCollectionAssembler, keyCollectionAssembler,

View File

@ -110,11 +110,6 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab
return getFetchContainer(); return getFetchContainer();
} }
@Override
public boolean isNullable() {
return nullable;
}
@Override @Override
public DomainResultAssembler createAssembler( public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,

View File

@ -61,11 +61,6 @@ public abstract class AbstractNonLazyEntityFetch extends AbstractFetchParent imp
return (Fetchable) getEntityValuedModelPart(); return (Fetchable) getEntityValuedModelPart();
} }
@Override
public boolean isNullable() {
return nullable;
}
@Override @Override
public DomainResultAssembler createAssembler( public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,

View File

@ -54,11 +54,6 @@ public class EntityFetchDelayedImpl extends AbstractNonJoinedEntityFetch {
return false; return false;
} }
@Override
public boolean isNullable() {
return nullable;
}
@Override @Override
public DomainResultAssembler createAssembler( public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,

View File

@ -52,11 +52,6 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
return false; return false;
} }
@Override
public boolean isNullable() {
return nullable;
}
@Override @Override
public DomainResultAssembler createAssembler( public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,

View File

@ -88,11 +88,6 @@ public class BiDirectionalFetchImpl implements BiDirectionalFetch, Association {
return fetchable.getJavaTypeDescriptor(); return fetchable.getJavaTypeDescriptor();
} }
@Override
public boolean isNullable() {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override @Override
public DomainResultAssembler createAssembler( public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,

View File

@ -10,6 +10,7 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.sql.results.jdbc.spi.JdbcValues; import org.hibernate.sql.results.jdbc.spi.JdbcValues;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
@ -47,7 +48,8 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
RowProcessingStateStandardImpl rowProcessingState, RowProcessingStateStandardImpl rowProcessingState,
RowReader<R> rowReader) { RowReader<R> rowReader) {
try { try {
session.getPersistenceContext().getLoadContexts().register( jdbcValuesSourceProcessingState ); final PersistenceContext persistenceContext = session.getPersistenceContext();
persistenceContext.getLoadContexts().register( jdbcValuesSourceProcessingState );
boolean uniqueRows = false; boolean uniqueRows = false;
final Class<R> resultJavaType = rowReader.getResultJavaType(); final Class<R> resultJavaType = rowReader.getResultJavaType();
@ -76,6 +78,7 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
rowProcessingState.finishRowProcessing(); rowProcessingState.finishRowProcessing();
} }
persistenceContext.initializeNonLazyCollections();
return results; return results;
} }
catch (SQLException e) { catch (SQLException e) {