Skip to content

Commit

Permalink
HHH-17030 Rework the initializer interactions and polish the interfac…
Browse files Browse the repository at this point in the history
…e design
  • Loading branch information
beikov committed May 22, 2024
1 parent 3263ac4 commit d02d8d7
Show file tree
Hide file tree
Showing 116 changed files with 4,268 additions and 3,068 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,13 @@ private void visitEmbeddedAttributeMapping(
PersistenceContext persistenceContext) {
if ( object != null ) {
final EmbeddableMappingType descriptor = attributeMapping.getEmbeddableTypeDescriptor();
final EmbeddableMappingType.ConcreteEmbeddableType concreteEmbeddableType = descriptor.findSubtypeBySubclass(
object.getClass().getName()
);
final AttributeMappingsList attributeMappings = descriptor.getAttributeMappings();
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attribute = attributeMappings.get( i );
if ( descriptor.declaresAttribute( object.getClass().getName(), attributeMapping ) ) {
if ( concreteEmbeddableType.declaresAttribute( attribute ) ) {
if ( attribute.isPluralAttributeMapping() ) {
addCollectionKey(
attribute.asPluralAttributeMapping(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.InitializerParent;
import org.hibernate.sql.results.graph.collection.CollectionInitializer;

/**
Expand Down Expand Up @@ -41,7 +42,7 @@ public interface CollectionInitializerProducer {
* @param collectionValueKeyAssembler allows creation of a
* {@link org.hibernate.sql.results.graph.DomainResult} for
* either side of the collection foreign key
* @deprecated Use {@link #produceInitializer(NavigablePath, PluralAttributeMapping, FetchParentAccess, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState)} instead
* @deprecated Use {@link #produceInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState)} instead
*/
@Deprecated(forRemoval = true)
CollectionInitializer produceInitializer(
Expand All @@ -56,7 +57,7 @@ CollectionInitializer produceInitializer(
default CollectionInitializer produceInitializer(
NavigablePath navigablePath,
PluralAttributeMapping attribute,
FetchParentAccess parentAccess,
InitializerParent parent,
LockMode lockMode,
DomainResult<?> collectionKeyResult,
DomainResult<?> collectionValueKeyResult,
Expand All @@ -67,30 +68,30 @@ default CollectionInitializer produceInitializer(
if ( collectionKeyResult == null ) {
collectionKeyAssembler = null;
collectionValueKeyAssembler = collectionValueKeyResult.createResultAssembler(
null,
(InitializerParent) null,
creationState
);
}
else if ( collectionKeyResult == collectionValueKeyResult ) {
collectionKeyAssembler = collectionValueKeyAssembler = collectionKeyResult.createResultAssembler(
null,
(InitializerParent) null,
creationState
);
}
else {
collectionKeyAssembler = collectionKeyResult.createResultAssembler(
null,
(InitializerParent) null,
creationState
);
collectionValueKeyAssembler = collectionValueKeyResult.createResultAssembler(
null,
(InitializerParent) null,
creationState
);
}
return produceInitializer(
navigablePath,
attribute,
parentAccess,
(FetchParentAccess) parent,
lockMode,
collectionKeyAssembler,
collectionValueKeyAssembler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;

import org.jboss.logging.Logger;

Expand Down Expand Up @@ -271,19 +272,20 @@ public <T> void collectBatchLoadableEntityIds(

final LinkedHashSet<EntityKey> set =
batchLoadableEntityKeys.get( entityDescriptor.getEntityName() );
final EntityPersister entityPersister = entityDescriptor.getEntityPersister();
final Type identifierType = entityPersister.getIdentifierType();
if ( set != null ) {
for ( EntityKey key : set ) {
if ( checkForEnd && i == end ) {
// the first id found after the given id
return ids;
}

if ( entityDescriptor.getEntityPersister().getIdentifierType()
.isEqual( loadingId, key.getIdentifier() ) ) {
if ( identifierType.isEqual( loadingId, key.getIdentifier() ) ) {
end = i;
}
else {
if ( !isCached( key, entityDescriptor.getEntityPersister() ) ) {
if ( !isCached( key, entityPersister ) ) {
ids[i++] = key.getIdentifier();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
* @author Steve Ebersole
*/
public class FetchingScrollableResultsImpl<R> extends AbstractScrollableResults<R> {
private final EntityInitializer resultInitializer;

private R currentRow;

private int currentPosition;
Expand All @@ -50,17 +48,10 @@ public FetchingScrollableResultsImpl(
persistenceContext
);

resultInitializer = extractResultInitializer( rowReader );

this.maxPosition = jdbcValuesSourceProcessingState.getQueryOptions().getEffectiveLimit().getMaxRows();
beforeFirst = true;
}

private static <R> EntityInitializer extractResultInitializer(RowReader<R> rowReader) {
Initializer initializer = rowReader.getInitializers().get( rowReader.getInitializers().size() - 1 );
return initializer.asEntityInitializer(); //might return null when it's not an EntityInitializer (intentional)
}

@Override
protected R getCurrentRow() {
return currentRow;
Expand Down Expand Up @@ -332,7 +323,6 @@ private boolean prepareCurrentRow() {
if ( rowProcessingState.next() ) {
final EntityKey entityKey2 = getEntityKey();
if ( !entityKey.equals( entityKey2 ) ) {
resultInitializer.finishUpRow( rowProcessingState );
resultProcessed = true;
last = false;
}
Expand Down Expand Up @@ -364,9 +354,6 @@ private boolean isResultSetEmpty() {
}

private EntityKey getEntityKey() {
resultInitializer.resolveKey( getRowProcessingState() );
final EntityKey entityKey = resultInitializer.getEntityKey();
resultInitializer.finishUpRow( getRowProcessingState() );
return entityKey;
return getRowReader().resolveSingleResultEntityKey( getRowProcessingState() );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ private void makeEntityCircularReferenceSafe(
final StatefulPersistenceContext statefulPersistenceContext = (StatefulPersistenceContext) session.getPersistenceContext();

if ( ( isManagedEntity( entity ) ) ) {
statefulPersistenceContext.addEntity( entityKey, entity );
statefulPersistenceContext.addReferenceEntry(
entity,
Status.READ_ONLY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
*/
package org.hibernate.metamodel.mapping;

import java.util.Collection;
import java.util.Collections;
import java.util.function.BiConsumer;

import org.hibernate.internal.util.IndexedConsumer;
import org.hibernate.internal.util.MutableInteger;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.spi.NavigablePath;
Expand Down Expand Up @@ -52,16 +55,39 @@ default boolean isPolymorphic() {
return getDiscriminatorMapping() != null;
}

interface ConcreteEmbeddableType {

EmbeddableInstantiator getInstantiator();

int getSubclassId();

/**
* Returns {@code true} if the provided embeddable class contains the
* specified attribute mapping, {@code false} otherwise.
* @implNote This method always returns {@code true} for non-polymorphic embeddable types
*
* @param attributeMapping the attribute to check
*/
boolean declaresAttribute(AttributeMapping attributeMapping);

boolean declaresAttribute(int attributeIndex);

Object getDiscriminatorValue();
}

default ConcreteEmbeddableType findSubtypeByDiscriminator(Object discriminatorValue) {
return null;
}

default ConcreteEmbeddableType findSubtypeBySubclass(String subclassName) {
return null;
}

/**
* Returns {@code true} if the provided embeddable class contains the
* specified attribute mapping, {@code false} otherwise.
* @implNote This method always returns {@code true} for non-polymorphic embeddable types
*
* @param embeddableClassName the embeddable subclass in which the attribute must be declared
* @param attributeMapping the attribute to check
* Returns the concrete embeddable subtypes or an empty collection if {@link #isPolymorphic()} is {@code false}.
*/
default boolean declaresAttribute(String embeddableClassName, AttributeMapping attributeMapping) {
return true;
default Collection<ConcreteEmbeddableType> getConcreteEmbeddableTypes() {
return Collections.emptySet();
}

default SelectableMapping getAggregateMapping() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
package org.hibernate.metamodel.mapping.internal;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.Consumer;

import org.hibernate.MappingException;
Expand Down Expand Up @@ -47,6 +49,7 @@
import org.hibernate.metamodel.mapping.SelectableMappings;
import org.hibernate.metamodel.mapping.SelectablePath;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
Expand All @@ -68,14 +71,40 @@
/**
* Base support for EmbeddableMappingType implementations
*/
public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType {
public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType,
EmbeddableMappingType.ConcreteEmbeddableType {
final protected MutableAttributeMappingList attributeMappings;
protected SelectableMappings selectableMappings;

public AbstractEmbeddableMapping(MutableAttributeMappingList attributeMappings) {
this.attributeMappings = attributeMappings;
}

@Override
public EmbeddableInstantiator getInstantiator() {
return getRepresentationStrategy().getInstantiator();
}

@Override
public int getSubclassId() {
return 0;
}

@Override
public boolean declaresAttribute(AttributeMapping attributeMapping) {
return true;
}

@Override
public boolean declaresAttribute(int attributeIndex) {
return true;
}

@Override
public Object getDiscriminatorValue() {
return null;
}

@Override
public JavaType<?> getMappedJavaType() {
return getRepresentationStrategy().getMappedJavaType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.graph.InitializerParent;
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
Expand Down Expand Up @@ -572,6 +573,13 @@ public String getResultVariable() {
public DomainResultAssembler<Object[]> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}

@Override
public DomainResultAssembler<Object[]> createResultAssembler(
InitializerParent parent,
AssemblerCreationState creationState) {
return new AssemblerImpl(
fetches,
navigablePath,
Expand All @@ -591,7 +599,7 @@ public JavaType<Object[]> getResultJavaType() {
// FetchParent

@Override
public Initializer createInitializer(FetchParentAccess parentAccess, AssemblerCreationState creationState) {
public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) {
throw new UnsupportedOperationException( "Compound natural id mappings should not use an initializer" );
}

Expand Down Expand Up @@ -647,7 +655,7 @@ private AssemblerImpl(
this.subAssemblers = new DomainResultAssembler[fetches.size()];
int i = 0;
for ( Fetch fetch : fetches ) {
subAssemblers[i++] = fetch.createAssembler( null, creationState );
subAssemblers[i++] = fetch.createAssembler( (InitializerParent) null, creationState );
}
}

Expand All @@ -669,6 +677,18 @@ public void resolveState(RowProcessingState rowProcessingState) {
}
}

@Override
public <X> void forEachResultAssembler(BiConsumer<Initializer, X> consumer, X arg) {
for ( DomainResultAssembler<?> subAssembler : subAssemblers ) {
final Initializer initializer = subAssembler.getInitializer();
// In case of natural id mapping selection every initializer is a "result initializer",
// regardless of what Initializer#isResultInitializer reports
if ( initializer != null ) {
consumer.accept( initializer, arg );
}
}
}

@Override
public JavaType<Object[]> getAssembledJavaType() {
return jtd;
Expand Down
Loading

0 comments on commit d02d8d7

Please sign in to comment.