Implemented SelectEagerCollectionInitializer
This commit is contained in:
parent
2fa3889e5a
commit
6462218587
|
@ -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() ),
|
||||||
|
|
|
@ -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() ),
|
||||||
|
|
|
@ -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() ),
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() ),
|
||||||
|
|
|
@ -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() ),
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 );
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue