initial working support for root entity loading via HQL
This commit is contained in:
parent
00267022eb
commit
5500985afa
|
@ -0,0 +1,4 @@
|
||||||
|
== Todo tasks related to 6.0 development
|
||||||
|
|
||||||
|
* Currently filtering tests to limit tests run during builds from Gradle. This is done in `gradle/java-module.gradle` via a test.include filter
|
||||||
|
* Tests for hibernate-orm-modules are run but failures are ignored
|
|
@ -7,11 +7,12 @@
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||||
|
import org.hibernate.sql.results.spi.Fetchable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface BasicValuedModelPart extends BasicValuedMapping, ModelPart {
|
public interface BasicValuedModelPart extends BasicValuedMapping, ModelPart, Fetchable {
|
||||||
/**
|
/**
|
||||||
* The table expression (table name or subselect) that contains
|
* The table expression (table name or subselect) that contains
|
||||||
* the {@linkplain #getMappedColumnExpression mapped column}
|
* the {@linkplain #getMappedColumnExpression mapped column}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import java.util.function.Consumer;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.sql.ast.Clause;
|
import org.hibernate.sql.ast.Clause;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,4 +15,9 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
*/
|
*/
|
||||||
public interface MappingType extends ModelPart {
|
public interface MappingType extends ModelPart {
|
||||||
JavaTypeDescriptor getMappedJavaTypeDescriptor();
|
JavaTypeDescriptor getMappedJavaTypeDescriptor();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return getMappedJavaTypeDescriptor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.results.spi.DomainResult;
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a mapping of related to any part of the app's domain model - e.g.
|
* Describes a mapping of related to any part of the app's domain model - e.g.
|
||||||
|
@ -25,6 +26,7 @@ import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ModelPart extends MappingModelExpressable {
|
public interface ModelPart extends MappingModelExpressable {
|
||||||
|
JavaTypeDescriptor getJavaTypeDescriptor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a DomainResult for a specific reference to this ModelPart.
|
* Create a DomainResult for a specific reference to this ModelPart.
|
||||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.metamodel.mapping.internal;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
import org.hibernate.metamodel.mapping.MappingType;
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -36,6 +37,11 @@ public abstract class AbstractAttributeMapping implements AttributeMapping {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ManagedMappingType getDeclaringType() {
|
public ManagedMappingType getDeclaringType() {
|
||||||
return declaringType;
|
return declaringType;
|
||||||
|
|
|
@ -8,7 +8,9 @@ package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
@ -23,9 +25,12 @@ import org.hibernate.sql.ast.Clause;
|
||||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.results.internal.ScalarDomainResultImpl;
|
import org.hibernate.sql.results.internal.domain.basic.BasicFetch;
|
||||||
|
import org.hibernate.sql.results.internal.domain.basic.BasicResultImpl;
|
||||||
import org.hibernate.sql.results.spi.DomainResult;
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
@ -89,8 +94,21 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
||||||
TableGroup tableGroup,
|
TableGroup tableGroup,
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
DomainResultCreationState creationState) {
|
DomainResultCreationState creationState) {
|
||||||
|
final SqlSelection sqlSelection = resolveSqlSelection( tableGroup, creationState );
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
return new BasicResultImpl(
|
||||||
|
sqlSelection.getValuesArrayPosition(),
|
||||||
|
resultVariable,
|
||||||
|
getMappedTypeDescriptor().getMappedJavaTypeDescriptor(),
|
||||||
|
valueConverter,
|
||||||
|
navigablePath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqlSelection resolveSqlSelection(TableGroup tableGroup, DomainResultCreationState creationState) {
|
||||||
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
|
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
|
||||||
final SqlSelection sqlSelection = expressionResolver.resolveSqlSelection(
|
return expressionResolver.resolveSqlSelection(
|
||||||
expressionResolver.resolveSqlExpression(
|
expressionResolver.resolveSqlExpression(
|
||||||
SqlExpressionResolver.createColumnReferenceKey(
|
SqlExpressionResolver.createColumnReferenceKey(
|
||||||
getContainingTableExpression(),
|
getContainingTableExpression(),
|
||||||
|
@ -106,15 +124,6 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
||||||
valueConverter == null ? getMappedTypeDescriptor().getMappedJavaTypeDescriptor() : valueConverter.getRelationalJavaDescriptor(),
|
valueConverter == null ? getMappedTypeDescriptor().getMappedJavaTypeDescriptor() : valueConverter.getRelationalJavaDescriptor(),
|
||||||
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
|
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
|
||||||
);
|
);
|
||||||
|
|
||||||
//noinspection unchecked
|
|
||||||
return new ScalarDomainResultImpl(
|
|
||||||
sqlSelection.getValuesArrayPosition(),
|
|
||||||
resultVariable,
|
|
||||||
getMappedTypeDescriptor().getMappedJavaTypeDescriptor(),
|
|
||||||
valueConverter,
|
|
||||||
navigablePath
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -143,6 +152,30 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetch generateFetch(
|
||||||
|
FetchParent fetchParent,
|
||||||
|
FetchTiming fetchTiming,
|
||||||
|
boolean selected,
|
||||||
|
LockMode lockMode,
|
||||||
|
String resultVariable,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
final TableGroup tableGroup = creationState.getSqlAstCreationState()
|
||||||
|
.getFromClauseAccess()
|
||||||
|
.findTableGroup( fetchParent.getNavigablePath() );
|
||||||
|
final SqlSelection sqlSelection = resolveSqlSelection( tableGroup, creationState );
|
||||||
|
|
||||||
|
return new BasicFetch(
|
||||||
|
sqlSelection.getValuesArrayPosition(),
|
||||||
|
fetchParent,
|
||||||
|
this,
|
||||||
|
getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
||||||
|
getConverter(),
|
||||||
|
fetchTiming,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
||||||
if ( valueConverter != null ) {
|
if ( valueConverter != null ) {
|
||||||
|
@ -168,9 +201,4 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
||||||
TypeConfiguration typeConfiguration) {
|
TypeConfiguration typeConfiguration) {
|
||||||
action.accept( getJdbcMapping() );
|
action.accept( getJdbcMapping() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getStateArrayPosition() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,12 @@ import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.results.internal.ScalarDomainResultImpl;
|
import org.hibernate.sql.results.internal.domain.basic.BasicResultImpl;
|
||||||
import org.hibernate.sql.results.spi.DomainResult;
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,6 +89,11 @@ public class MappingModelCreationHelper {
|
||||||
valuesConsumer.consume( value, idType );
|
valuesConsumer.consume( value, idType );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> DomainResult<T> createDomainResult(
|
public <T> DomainResult<T> createDomainResult(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
|
@ -113,7 +119,7 @@ public class MappingModelCreationHelper {
|
||||||
);
|
);
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return new ScalarDomainResultImpl(
|
return new BasicResultImpl(
|
||||||
sqlSelection.getValuesArrayPosition(),
|
sqlSelection.getValuesArrayPosition(),
|
||||||
resultVariable,
|
resultVariable,
|
||||||
entityPersister.getIdentifierMapping().getMappedTypeDescriptor().getMappedJavaTypeDescriptor()
|
entityPersister.getIdentifierMapping().getMappedTypeDescriptor().getMappedJavaTypeDescriptor()
|
||||||
|
@ -177,6 +183,11 @@ public class MappingModelCreationHelper {
|
||||||
return ( (BasicValuedModelPart) entityPersister.getIdentifierType() ).getMappedTypeDescriptor();
|
return ( (BasicValuedModelPart) entityPersister.getIdentifierType() ).getMappedTypeDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> DomainResult<T> createDomainResult(
|
public <T> DomainResult<T> createDomainResult(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
|
@ -227,7 +238,12 @@ public class MappingModelCreationHelper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MappingType getMappedTypeDescriptor() {
|
public MappingType getMappedTypeDescriptor() {
|
||||||
return null;
|
return entityPersister;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.metamodel.model.domain;
|
||||||
import javax.persistence.metamodel.Attribute;
|
import javax.persistence.metamodel.Attribute;
|
||||||
|
|
||||||
import org.hibernate.metamodel.AttributeClassification;
|
import org.hibernate.metamodel.AttributeClassification;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,7 +16,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface PersistentAttribute<D,J> extends Attribute<D,J>, ModelPart {
|
public interface PersistentAttribute<D,J> extends Attribute<D,J> {
|
||||||
@Override
|
@Override
|
||||||
ManagedDomainType<D> getDeclaringType();
|
ManagedDomainType<D> getDeclaringType();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.metamodel.model.domain;
|
||||||
|
|
||||||
import javax.persistence.metamodel.SingularAttribute;
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
|
||||||
import org.hibernate.query.sqm.SqmJoinable;
|
import org.hibernate.query.sqm.SqmJoinable;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
|
||||||
|
@ -18,7 +17,7 @@ import org.hibernate.query.sqm.SqmPathSource;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SingularPersistentAttribute<D,J>
|
public interface SingularPersistentAttribute<D,J>
|
||||||
extends SingularAttribute<D,J>, PersistentAttribute<D,J>, ModelPart, SqmPathSource<J>, SqmJoinable {
|
extends SingularAttribute<D,J>, PersistentAttribute<D,J>, SqmPathSource<J>, SqmJoinable {
|
||||||
@Override
|
@Override
|
||||||
SimpleDomainType<J> getType();
|
SimpleDomainType<J> getType();
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
public abstract class AbstractAttribute<D,J,B> implements PersistentAttribute<D,J>, Serializable {
|
public abstract class AbstractAttribute<D,J,B> implements PersistentAttribute<D,J>, Serializable {
|
||||||
private final ManagedDomainType<D> declaringType;
|
private final ManagedDomainType<D> declaringType;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final JavaTypeDescriptor<J> attributeType;
|
private final JavaTypeDescriptor<J> attributeJtd;
|
||||||
|
|
||||||
private final AttributeClassification attributeClassification;
|
private final AttributeClassification attributeClassification;
|
||||||
|
|
||||||
|
@ -44,14 +44,14 @@ public abstract class AbstractAttribute<D,J,B> implements PersistentAttribute<D,
|
||||||
protected AbstractAttribute(
|
protected AbstractAttribute(
|
||||||
ManagedDomainType<D> declaringType,
|
ManagedDomainType<D> declaringType,
|
||||||
String name,
|
String name,
|
||||||
JavaTypeDescriptor<J> attributeType,
|
JavaTypeDescriptor<J> attributeJtd,
|
||||||
AttributeClassification attributeClassification,
|
AttributeClassification attributeClassification,
|
||||||
SimpleDomainType<B> valueType,
|
SimpleDomainType<B> valueType,
|
||||||
Member member,
|
Member member,
|
||||||
MetadataContext metadataContext) {
|
MetadataContext metadataContext) {
|
||||||
this.declaringType = declaringType;
|
this.declaringType = declaringType;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.attributeType = attributeType;
|
this.attributeJtd = attributeJtd;
|
||||||
this.attributeClassification = attributeClassification;
|
this.attributeClassification = attributeClassification;
|
||||||
this.valueType = valueType;
|
this.valueType = valueType;
|
||||||
this.member = member;
|
this.member = member;
|
||||||
|
@ -64,7 +64,7 @@ public abstract class AbstractAttribute<D,J,B> implements PersistentAttribute<D,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<J> getJavaType() {
|
public Class<J> getJavaType() {
|
||||||
return attributeType.getJavaType();
|
return attributeJtd.getJavaType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleDomainType<B> getSqmPathType() {
|
public SimpleDomainType<B> getSqmPathType() {
|
||||||
|
@ -73,7 +73,7 @@ public abstract class AbstractAttribute<D,J,B> implements PersistentAttribute<D,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptor<J> getAttributeJavaTypeDescriptor() {
|
public JavaTypeDescriptor<J> getAttributeJavaTypeDescriptor() {
|
||||||
return attributeType;
|
return attributeJtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6413,9 +6413,10 @@ public abstract class AbstractEntityPersister
|
||||||
EntityMappingType treatTargetType) {
|
EntityMappingType treatTargetType) {
|
||||||
visitStateArrayContributors(
|
visitStateArrayContributors(
|
||||||
mapping -> {
|
mapping -> {
|
||||||
if ( mapping.isDeclaredOnTypeOrSuperType( treatTargetType ) ) {
|
// treat limits are already handled in `#visitAttributeMappings` (called from `#visitStateArrayContributors`)
|
||||||
|
// if ( mapping.isDeclaredOnTypeOrSuperType( treatTargetType ) ) {
|
||||||
fetchableConsumer.accept( mapping );
|
fetchableConsumer.accept( mapping );
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
treatTargetType
|
treatTargetType
|
||||||
);
|
);
|
||||||
|
@ -6443,7 +6444,7 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
declaredAttributeMappings.values().forEach( action );
|
declaredAttributeMappings.values().forEach( action );
|
||||||
|
|
||||||
if ( targetType == null ) {
|
if ( targetType == null || targetType.isTypeOrSuperType( this ) ) {
|
||||||
visitSubTypeAttributeMappings( action );
|
visitSubTypeAttributeMappings( action );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBinding;
|
import org.hibernate.sql.exec.spi.JdbcParameterBinding;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.sql.results.internal.domain;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.spi.Fetch;
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
|
@ -33,6 +34,11 @@ public abstract class AbstractFetchParent implements FetchParent {
|
||||||
this.fetches = creationState.visitFetches( this );
|
this.fetches = creationState.visitFetches( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ManagedMappingType getReferencedMappingType() {
|
||||||
|
return (ManagedMappingType) fetchContainer;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NavigablePath getNavigablePath() {
|
public NavigablePath getNavigablePath() {
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.sql.results.internal.domain;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.results.spi.AssemblerCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.BiDirectionalFetch;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResultAssembler;
|
||||||
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParentAccess;
|
||||||
|
import org.hibernate.sql.results.spi.Fetchable;
|
||||||
|
import org.hibernate.sql.results.spi.Initializer;
|
||||||
|
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingOptions;
|
||||||
|
import org.hibernate.sql.results.spi.RowProcessingState;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of BiDirectionalFetch for the `oa` case - the bi-dir fetch
|
||||||
|
* refers to another fetch (`a`)
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class BiDirectionalFetchImpl implements BiDirectionalFetch {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final FetchParent fetchParent;
|
||||||
|
private final Fetch referencedFetch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the bi-dir fetch
|
||||||
|
*
|
||||||
|
* @param navigablePath `Person(p).address.owner.address`
|
||||||
|
* @param fetchParent The parent for the `oa` fetch is `o`
|
||||||
|
* @param referencedFetch `RootBiDirectionalFetchImpl(a)` (because `a` is itself also a bi-dir fetch referring to the `p root)
|
||||||
|
*/
|
||||||
|
public BiDirectionalFetchImpl(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
FetchParent fetchParent,
|
||||||
|
Fetch referencedFetch) {
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.fetchParent = fetchParent;
|
||||||
|
this.referencedFetch = referencedFetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getReferencedPath() {
|
||||||
|
return referencedFetch.getNavigablePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchParent getFetchParent() {
|
||||||
|
return fetchParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetchable getFetchedMapping() {
|
||||||
|
return referencedFetch.getFetchedMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResultAssembler createAssembler(
|
||||||
|
FetchParentAccess parentAccess,
|
||||||
|
Consumer<Initializer> collector,
|
||||||
|
AssemblerCreationState creationState) {
|
||||||
|
return new CircularFetchAssembler(
|
||||||
|
getReferencedPath(),
|
||||||
|
referencedFetch.getFetchedMapping().getJavaTypeDescriptor()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CircularFetchAssembler implements DomainResultAssembler {
|
||||||
|
private final NavigablePath circularPath;
|
||||||
|
private final JavaTypeDescriptor javaTypeDescriptor;
|
||||||
|
|
||||||
|
public CircularFetchAssembler(
|
||||||
|
NavigablePath circularPath,
|
||||||
|
JavaTypeDescriptor javaTypeDescriptor) {
|
||||||
|
this.circularPath = circularPath;
|
||||||
|
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
|
||||||
|
return rowProcessingState.resolveInitializer( circularPath ).getInitializedInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor getAssembledJavaTypeDescriptor() {
|
||||||
|
return javaTypeDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.sql.results.internal.domain;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.engine.FetchStrategy;
|
||||||
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.results.spi.AssemblerCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.BiDirectionalFetch;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResultAssembler;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.EntityResult;
|
||||||
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParentAccess;
|
||||||
|
import org.hibernate.sql.results.spi.Fetchable;
|
||||||
|
import org.hibernate.sql.results.spi.Initializer;
|
||||||
|
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingOptions;
|
||||||
|
import org.hibernate.sql.results.spi.RowProcessingState;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class RootBiDirectionalFetchImpl implements BiDirectionalFetch, Fetchable {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final FetchParent fetchParent;
|
||||||
|
private final EntityResult referencedRoot;
|
||||||
|
|
||||||
|
public RootBiDirectionalFetchImpl(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
FetchParent fetchParent,
|
||||||
|
EntityResult referencedRoot) {
|
||||||
|
this.fetchParent = fetchParent;
|
||||||
|
this.referencedRoot = referencedRoot;
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getReferencedPath() {
|
||||||
|
return referencedRoot.getNavigablePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchParent getFetchParent() {
|
||||||
|
return fetchParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetchable getFetchedMapping() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResultAssembler createAssembler(
|
||||||
|
FetchParentAccess parentAccess,
|
||||||
|
Consumer<Initializer> collector,
|
||||||
|
AssemblerCreationState creationState) {
|
||||||
|
return new CircularFetchAssembler(
|
||||||
|
getReferencedPath(),
|
||||||
|
referencedRoot.getResultJavaTypeDescriptor()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFetchableName() {
|
||||||
|
// An entity itself is not fetchable
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return referencedRoot.getResultJavaTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchStrategy getMappedFetchStrategy() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetch generateFetch(
|
||||||
|
FetchParent fetchParent,
|
||||||
|
FetchTiming fetchTiming,
|
||||||
|
boolean selected,
|
||||||
|
LockMode lockMode,
|
||||||
|
String resultVariable,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CircularFetchAssembler implements DomainResultAssembler {
|
||||||
|
private final NavigablePath circularPath;
|
||||||
|
private final JavaTypeDescriptor javaTypeDescriptor;
|
||||||
|
|
||||||
|
public CircularFetchAssembler(
|
||||||
|
NavigablePath circularPath,
|
||||||
|
JavaTypeDescriptor javaTypeDescriptor) {
|
||||||
|
this.circularPath = circularPath;
|
||||||
|
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
|
||||||
|
Initializer initializer = rowProcessingState.resolveInitializer( circularPath );
|
||||||
|
if ( initializer.getInitializedInstance() == null ) {
|
||||||
|
initializer.resolveKey( rowProcessingState );
|
||||||
|
initializer.resolveInstance( rowProcessingState );
|
||||||
|
initializer.initializeInstance( rowProcessingState );
|
||||||
|
}
|
||||||
|
return initializer.getInitializedInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor getAssembledJavaTypeDescriptor() {
|
||||||
|
return javaTypeDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.sql.results.internal.domain.basic;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.results.spi.AssemblerCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResultAssembler;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParentAccess;
|
||||||
|
import org.hibernate.sql.results.spi.Fetchable;
|
||||||
|
import org.hibernate.sql.results.spi.Initializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class BasicFetch implements Fetch {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final FetchParent fetchParent;
|
||||||
|
private final BasicValuedModelPart valuedMapping;
|
||||||
|
private final boolean nullable;
|
||||||
|
|
||||||
|
private final BasicResultAssembler assembler;
|
||||||
|
|
||||||
|
private final FetchTiming fetchTiming;
|
||||||
|
|
||||||
|
public BasicFetch(
|
||||||
|
int valuesArrayPosition,
|
||||||
|
FetchParent fetchParent,
|
||||||
|
BasicValuedModelPart valuedMapping,
|
||||||
|
boolean nullable,
|
||||||
|
BasicValueConverter valueConverter,
|
||||||
|
FetchTiming fetchTiming,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
this.nullable = nullable;
|
||||||
|
this.navigablePath = fetchParent.getNavigablePath().append( valuedMapping.getFetchableName() );
|
||||||
|
|
||||||
|
this.fetchParent = fetchParent;
|
||||||
|
this.valuedMapping = valuedMapping;
|
||||||
|
this.fetchTiming = fetchTiming;
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
this.assembler = new BasicResultAssembler(
|
||||||
|
valuesArrayPosition,
|
||||||
|
valuedMapping.getJavaTypeDescriptor(),
|
||||||
|
valueConverter
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchParent getFetchParent() {
|
||||||
|
return fetchParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetchable getFetchedMapping() {
|
||||||
|
return valuedMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResultAssembler createAssembler(
|
||||||
|
FetchParentAccess parentAccess,
|
||||||
|
Consumer<Initializer> collector,
|
||||||
|
AssemblerCreationState creationState) {
|
||||||
|
return assembler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.results.internal;
|
package org.hibernate.sql.results.internal.domain.basic;
|
||||||
|
|
||||||
import org.hibernate.Internal;
|
import org.hibernate.Internal;
|
||||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.results.internal;
|
package org.hibernate.sql.results.internal.domain.basic;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class ScalarDomainResultImpl<T> implements ScalarDomainResult<T> {
|
public class BasicResultImpl<T> implements ScalarDomainResult<T> {
|
||||||
private final String resultVariable;
|
private final String resultVariable;
|
||||||
private final JavaTypeDescriptor<T> javaTypeDescriptor;
|
private final JavaTypeDescriptor<T> javaTypeDescriptor;
|
||||||
|
|
||||||
|
@ -28,14 +28,14 @@ public class ScalarDomainResultImpl<T> implements ScalarDomainResult<T> {
|
||||||
|
|
||||||
private final DomainResultAssembler<T> assembler;
|
private final DomainResultAssembler<T> assembler;
|
||||||
|
|
||||||
public ScalarDomainResultImpl(
|
public BasicResultImpl(
|
||||||
int jdbcValuesArrayPosition,
|
int jdbcValuesArrayPosition,
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
JavaTypeDescriptor<T> javaTypeDescriptor) {
|
JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
this( jdbcValuesArrayPosition, resultVariable, javaTypeDescriptor, (NavigablePath) null );
|
this( jdbcValuesArrayPosition, resultVariable, javaTypeDescriptor, (NavigablePath) null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScalarDomainResultImpl(
|
public BasicResultImpl(
|
||||||
int jdbcValuesArrayPosition,
|
int jdbcValuesArrayPosition,
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
JavaTypeDescriptor<T> javaTypeDescriptor,
|
JavaTypeDescriptor<T> javaTypeDescriptor,
|
||||||
|
@ -48,7 +48,7 @@ public class ScalarDomainResultImpl<T> implements ScalarDomainResult<T> {
|
||||||
this.assembler = new BasicResultAssembler<>( jdbcValuesArrayPosition, javaTypeDescriptor );
|
this.assembler = new BasicResultAssembler<>( jdbcValuesArrayPosition, javaTypeDescriptor );
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScalarDomainResultImpl(
|
public BasicResultImpl(
|
||||||
int valuesArrayPosition,
|
int valuesArrayPosition,
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
JavaTypeDescriptor<T> javaTypeDescriptor,
|
JavaTypeDescriptor<T> javaTypeDescriptor,
|
||||||
|
@ -56,7 +56,7 @@ public class ScalarDomainResultImpl<T> implements ScalarDomainResult<T> {
|
||||||
this( valuesArrayPosition, resultVariable, javaTypeDescriptor, valueConverter, null );
|
this( valuesArrayPosition, resultVariable, javaTypeDescriptor, valueConverter, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScalarDomainResultImpl(
|
public BasicResultImpl(
|
||||||
int valuesArrayPosition,
|
int valuesArrayPosition,
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
JavaTypeDescriptor<T> javaTypeDescriptor,
|
JavaTypeDescriptor<T> javaTypeDescriptor,
|
|
@ -92,16 +92,16 @@ public abstract class AbstractEntityMappingNode extends AbstractFetchParent impl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
entityDescriptor.visitAttributeMappings(
|
// entityDescriptor.visitAttributeMappings(
|
||||||
mapping -> attributeDomainResults.add(
|
// mapping -> attributeDomainResults.add(
|
||||||
mapping.createDomainResult(
|
// mapping.createDomainResult(
|
||||||
navigablePath.append( mapping.getAttributeName() ),
|
// navigablePath.append( mapping.getAttributeName() ),
|
||||||
entityTableGroup,
|
// entityTableGroup,
|
||||||
null,
|
// null,
|
||||||
creationState
|
// creationState
|
||||||
)
|
// )
|
||||||
)
|
// )
|
||||||
);
|
// );
|
||||||
|
|
||||||
// todo (6.0) : handle other special navigables such as discriminator, row-id, tenant-id, etc
|
// todo (6.0) : handle other special navigables such as discriminator, row-id, tenant-id, etc
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.spi;
|
||||||
|
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @asciidoc
|
||||||
|
*
|
||||||
|
* Marker interface for Fetches that are actually references to
|
||||||
|
* another fetch based on "normalized navigable path"
|
||||||
|
*
|
||||||
|
* The following query is used throughout the javadocs for these impls
|
||||||
|
* to help describe what it going on and why certain methods do certain things.
|
||||||
|
*
|
||||||
|
* ````
|
||||||
|
* @Entity
|
||||||
|
* class Person {
|
||||||
|
* ...
|
||||||
|
* @ManyToOne(mappedBy="owner")
|
||||||
|
* Address getAddress() {...}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @Entity
|
||||||
|
* class Address {
|
||||||
|
* ...
|
||||||
|
* @ManyToOne
|
||||||
|
* Person getOwner() {...}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* from Person p
|
||||||
|
* join fetch p.address a
|
||||||
|
* join fetch a.owner o
|
||||||
|
* join fetch o.address oa
|
||||||
|
* ````
|
||||||
|
*
|
||||||
|
* Here we have one root result and 3 fetches. 2 of the fetches are bi-directional:
|
||||||
|
*
|
||||||
|
* `o`:: The paths `p` and `p.address.owner` (aliased as `o`) are the same table reference in SQL terms
|
||||||
|
* `oa`:: The paths `p.address` and `p.address.owner.address` (aliased as `oa`) are again the same table reference
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface BiDirectionalFetch extends Fetch {
|
||||||
|
/**
|
||||||
|
* The NavigablePath for the DomainResult or Fetch that this Fetch refers to.
|
||||||
|
*
|
||||||
|
* For `o`, the referenced path is `p`. For `oa`, it's `p.address`
|
||||||
|
*
|
||||||
|
* Different from {@link #getNavigablePath()} which returns this fetch's path, i.e.
|
||||||
|
* `p.address.owner` and `p.address.owner.address` respectively
|
||||||
|
*/
|
||||||
|
NavigablePath getReferencedPath();
|
||||||
|
}
|
|
@ -7,8 +7,9 @@
|
||||||
package org.hibernate.sql.results.spi;
|
package org.hibernate.sql.results.spi;
|
||||||
|
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.results.internal.domain.BiDirectionalFetchImpl;
|
||||||
|
import org.hibernate.sql.results.internal.domain.RootBiDirectionalFetchImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maintains state while processing a Fetch graph to be able to detect
|
* Maintains state while processing a Fetch graph to be able to detect
|
||||||
|
@ -19,57 +20,36 @@ import org.hibernate.query.NavigablePath;
|
||||||
public class CircularFetchDetector {
|
public class CircularFetchDetector {
|
||||||
|
|
||||||
public Fetch findBiDirectionalFetch(FetchParent fetchParent, Fetchable fetchable) {
|
public Fetch findBiDirectionalFetch(FetchParent fetchParent, Fetchable fetchable) {
|
||||||
// bi-directional references are a special case that need special treatment.
|
if ( ! fetchable.isCircular( fetchParent ) ) {
|
||||||
//
|
return null;
|
||||||
// `p.address.resident.homeAddress
|
}
|
||||||
//
|
|
||||||
// what we mean is a fetch path like `a.parent.child.parent`. here the terminal
|
assert fetchParent instanceof Fetch;
|
||||||
// `parent` name is the same reference as its parent's (`a.parent.child`)
|
final Fetch fetchParentAsFetch = (Fetch) fetchParent;
|
||||||
// parent's (a.parent`) path.
|
|
||||||
//
|
|
||||||
// In such a case we want to (mostly) reuse the "parent parent" path fetch
|
|
||||||
//
|
|
||||||
// see if we have such a case...
|
|
||||||
|
|
||||||
final NavigablePath parentParentPath = fetchParent.getNavigablePath().getParent();
|
final NavigablePath parentParentPath = fetchParent.getNavigablePath().getParent();
|
||||||
if ( parentParentPath != null ) {
|
assert fetchParent.getNavigablePath().getParent() != null;
|
||||||
if ( fetchable.isCircular( fetchParent ) ) {
|
|
||||||
if ( fetchParent instanceof Fetch ) {
|
|
||||||
final FetchParent parentFetchParent = ( (Fetch) fetchParent ).getFetchParent();
|
|
||||||
|
|
||||||
// we do...
|
assert fetchParentAsFetch.getFetchParent().getNavigablePath().equals( parentParentPath );
|
||||||
//
|
|
||||||
// in other words, the `Fetchable`'s `NavigablePath`, relative to its FetchParent here would
|
|
||||||
// be:
|
|
||||||
// a.parent.child.parent
|
|
||||||
//
|
|
||||||
// it's parentPath is `a.parent.child` so its parentParentPath is `a.parent`. so this Fetchable's
|
|
||||||
// path is really the same reference as its parentParentPath. This is a special case, handled here...
|
|
||||||
|
|
||||||
// first, this *should* mean we have already "seen" the Fetch generated parentParentPath. So
|
if ( fetchParentAsFetch.getFetchParent() instanceof Fetch ) {
|
||||||
// look up in the `navigablePathFetchMap` to get that Fetch
|
return new BiDirectionalFetchImpl(
|
||||||
|
fetchParent.getNavigablePath().append( fetchable.getFetchableName() ),
|
||||||
// and use it to create and register the "bi directional" form
|
fetchParent,
|
||||||
|
fetchParentAsFetch
|
||||||
final NavigablePath fetchableNavigablePath = fetchParent.getNavigablePath().append( fetchable.getFetchableName() );
|
);
|
||||||
|
|
||||||
// return new BiDirectionalFetchImpl(
|
|
||||||
// parentFetchParent,
|
|
||||||
// fetchableNavigablePath
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// return new RootBiDirectionalFetchImpl(
|
assert fetchParentAsFetch instanceof EntityResult;
|
||||||
// new NavigablePath( fetchable.getJavaTypeDescriptor().getJavaType().getName() ),
|
|
||||||
// fetchable.getJavaTypeDescriptor(),
|
|
||||||
// new NavigablePath( fetchable.getNavigableName() )
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return null;
|
// note : the "`fetchParentAsFetch` is `RootBiDirectionalFetchImpl`" case would
|
||||||
|
// be handled in the `Fetch` block since `RootBiDirectionalFetchImpl` is a Fetch
|
||||||
|
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
return new RootBiDirectionalFetchImpl(
|
||||||
|
fetchParent.getNavigablePath().append( fetchable.getFetchableName() ),
|
||||||
|
fetchParent,
|
||||||
|
(EntityResult) fetchParentAsFetch
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.sql.results.spi;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +19,11 @@ import org.hibernate.query.NavigablePath;
|
||||||
public interface FetchParent {
|
public interface FetchParent {
|
||||||
FetchableContainer getReferencedMappingContainer();
|
FetchableContainer getReferencedMappingContainer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This parent's type
|
||||||
|
*/
|
||||||
|
ManagedMappingType getReferencedMappingType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the property path to this parent
|
* Get the property path to this parent
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -37,6 +37,11 @@ public interface BasicType<T> extends Type, BasicDomainType<T>, MappingType, Bas
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return getMappedJavaTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default JdbcMapping getJdbcMapping() {
|
default JdbcMapping getJdbcMapping() {
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -12,7 +12,6 @@ import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||||
import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter;
|
import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter;
|
||||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||||
import org.hibernate.metamodel.model.convert.spi.EnumValueConverter;
|
|
||||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender;
|
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender;
|
||||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
|
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
@ -31,15 +30,12 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcSelect;
|
import org.hibernate.sql.exec.spi.JdbcSelect;
|
||||||
import org.hibernate.sql.results.internal.BasicResultAssembler;
|
import org.hibernate.sql.results.internal.domain.basic.BasicResultAssembler;
|
||||||
import org.hibernate.sql.results.internal.ScalarDomainResultImpl;
|
import org.hibernate.sql.results.internal.domain.basic.BasicResultImpl;
|
||||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||||
import org.hibernate.sql.results.spi.DomainResult;
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
import org.hibernate.sql.results.spi.DomainResultAssembler;
|
import org.hibernate.sql.results.spi.DomainResultAssembler;
|
||||||
import org.hibernate.type.CustomType;
|
|
||||||
import org.hibernate.type.EnumType;
|
|
||||||
import org.hibernate.type.internal.StandardBasicTypeImpl;
|
import org.hibernate.type.internal.StandardBasicTypeImpl;
|
||||||
import org.hibernate.usertype.UserType;
|
|
||||||
|
|
||||||
import org.hibernate.testing.hamcrest.AssignableMatcher;
|
import org.hibernate.testing.hamcrest.AssignableMatcher;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
@ -196,8 +192,8 @@ public class SmokeTests {
|
||||||
|
|
||||||
assertThat( sqlAst.getDomainResultDescriptors().size(), is( 1 ) );
|
assertThat( sqlAst.getDomainResultDescriptors().size(), is( 1 ) );
|
||||||
final DomainResult domainResult = sqlAst.getDomainResultDescriptors().get( 0 );
|
final DomainResult domainResult = sqlAst.getDomainResultDescriptors().get( 0 );
|
||||||
assertThat( domainResult, instanceOf( ScalarDomainResultImpl.class ) );
|
assertThat( domainResult, instanceOf( BasicResultImpl.class ) );
|
||||||
final ScalarDomainResultImpl scalarDomainResult = (ScalarDomainResultImpl) domainResult;
|
final BasicResultImpl scalarDomainResult = (BasicResultImpl) domainResult;
|
||||||
assertThat( scalarDomainResult.getAssembler(), instanceOf( BasicResultAssembler.class ) );
|
assertThat( scalarDomainResult.getAssembler(), instanceOf( BasicResultAssembler.class ) );
|
||||||
final BasicResultAssembler<?> assembler = (BasicResultAssembler) scalarDomainResult.getAssembler();
|
final BasicResultAssembler<?> assembler = (BasicResultAssembler) scalarDomainResult.getAssembler();
|
||||||
assertThat( assembler.getValueConverter(), notNullValue() );
|
assertThat( assembler.getValueConverter(), notNullValue() );
|
||||||
|
@ -207,7 +203,7 @@ public class SmokeTests {
|
||||||
"e"
|
"e"
|
||||||
).append( "gender" );
|
).append( "gender" );
|
||||||
assertThat( domainResult.getNavigablePath(), equalTo( expectedSelectedPath ) );
|
assertThat( domainResult.getNavigablePath(), equalTo( expectedSelectedPath ) );
|
||||||
assertThat( domainResult, instanceOf( ScalarDomainResultImpl.class ) );
|
assertThat( domainResult, instanceOf( BasicResultImpl.class ) );
|
||||||
|
|
||||||
// ScalarDomainResultImpl creates and caches the assembler at its creation.
|
// ScalarDomainResultImpl creates and caches the assembler at its creation.
|
||||||
// this just gets access to that cached one
|
// this just gets access to that cached one
|
||||||
|
|
Loading…
Reference in New Issue