Add query plan cache statistics for native queries and implement proper caching
This commit is contained in:
parent
1184a5963b
commit
3ea5a066ed
|
@ -113,4 +113,36 @@ public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R
|
|||
public JavaType<R> getRelationalJavaTypeDescriptor() {
|
||||
return jdbcJtd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JpaAttributeConverterImpl<?, ?> that = (JpaAttributeConverterImpl<?, ?>) o;
|
||||
|
||||
if ( !attributeConverterBean.equals( that.attributeConverterBean ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !converterJtd.equals( that.converterJtd ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !domainJtd.equals( that.domainJtd ) ) {
|
||||
return false;
|
||||
}
|
||||
return jdbcJtd.equals( that.jdbcJtd );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = attributeConverterBean.hashCode();
|
||||
result = 31 * result + converterJtd.hashCode();
|
||||
result = 31 * result + domainJtd.hashCode();
|
||||
result = 31 * result + jdbcJtd.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ import org.hibernate.persister.entity.Queryable;
|
|||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.spi.DynamicModelJtd;
|
||||
import org.hibernate.type.descriptor.java.spi.EntityJavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -195,7 +196,7 @@ public class JpaMetamodelImpl implements JpaMetamodel, Serializable {
|
|||
@Override
|
||||
public <X> EmbeddableDomainType<X> embeddable(Class<X> cls) {
|
||||
final ManagedType<?> type = jpaManagedTypeMap.get( cls );
|
||||
if ( !( type instanceof EntityDomainType<?> ) ) {
|
||||
if ( !( type instanceof EmbeddableDomainType<?> ) ) {
|
||||
throw new IllegalArgumentException( "Not an embeddable: " + cls.getName() );
|
||||
}
|
||||
//noinspection unchecked
|
||||
|
@ -503,13 +504,16 @@ public class JpaMetamodelImpl implements JpaMetamodel, Serializable {
|
|||
if ( embeddable.getJavaType() != null && embeddable.getJavaType() != Map.class ) {
|
||||
this.jpaEmbeddables.add( embeddable );
|
||||
this.jpaManagedTypes.add( embeddable );
|
||||
this.jpaManagedTypeMap.put( embeddable.getJavaType(), embeddable );
|
||||
if ( !( embeddable.getExpressableJavaTypeDescriptor() instanceof EntityJavaTypeDescriptor<?> ) ) {
|
||||
this.jpaManagedTypeMap.put( embeddable.getJavaType(), embeddable );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ENABLED:
|
||||
this.jpaEmbeddables.add( embeddable );
|
||||
this.jpaManagedTypes.add( embeddable );
|
||||
if ( embeddable.getJavaType() != null ) {
|
||||
if ( embeddable.getJavaType() != null
|
||||
&& !( embeddable.getExpressableJavaTypeDescriptor() instanceof EntityJavaTypeDescriptor<?> ) ) {
|
||||
this.jpaManagedTypeMap.put( embeddable.getJavaType(), embeddable );
|
||||
}
|
||||
break;
|
||||
|
@ -517,7 +521,9 @@ public class JpaMetamodelImpl implements JpaMetamodel, Serializable {
|
|||
if ( embeddable.getJavaType() == null ) {
|
||||
throw new UnsupportedOperationException( "ANY not supported" );
|
||||
}
|
||||
this.jpaManagedTypeMap.put( embeddable.getJavaType(), embeddable );
|
||||
if ( !( embeddable.getExpressableJavaTypeDescriptor() instanceof EntityJavaTypeDescriptor<?> ) ) {
|
||||
this.jpaManagedTypeMap.put( embeddable.getJavaType(), embeddable );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,11 @@ public class EntityDomainResultBuilder implements ResultBuilder {
|
|||
return entityDescriptor.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -77,4 +82,22 @@ public class EntityDomainResultBuilder implements ResultBuilder {
|
|||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final EntityDomainResultBuilder that = (EntityDomainResultBuilder) o;
|
||||
return entityDescriptor.equals( that.entityDescriptor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return entityDescriptor.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,4 +39,28 @@ public class ScalarDomainResultBuilder<T> implements ResultBuilder {
|
|||
DomainResultCreationState domainResultCreationState) {
|
||||
return new BasicResult<>( resultPosition, null, typeDescriptor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScalarDomainResultBuilder<?> that = (ScalarDomainResultBuilder<?>) o;
|
||||
|
||||
return typeDescriptor.equals( that.typeDescriptor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return typeDescriptor.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,11 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation
|
|||
|
||||
@Override
|
||||
public <R> SelectQueryPlan<R> resolveSelectQueryPlan(Key key, Supplier<SelectQueryPlan<R>> creator) {
|
||||
return null;
|
||||
final StatisticsImplementor statistics = statisticsSupplier.get();
|
||||
if ( statistics.isStatisticsEnabled() ) {
|
||||
statistics.queryPlanCacheMiss( key.getQueryString() );
|
||||
}
|
||||
return creator.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,7 +65,7 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation
|
|||
|
||||
@Override
|
||||
public HqlInterpretation resolveHqlInterpretation(String queryString, Function<String, SqmStatement<?>> creator) {
|
||||
StatisticsImplementor statistics = statisticsSupplier.get();
|
||||
final StatisticsImplementor statistics = statisticsSupplier.get();
|
||||
final boolean stats = statistics.isStatisticsEnabled();
|
||||
final long startTime = ( stats ) ? System.nanoTime() : 0L;
|
||||
final SqmStatement<?> sqmStatement = creator.apply( queryString );
|
||||
|
@ -76,7 +80,6 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation
|
|||
else {
|
||||
domainParameterXref = DomainParameterXref.from( sqmStatement );
|
||||
parameterMetadata = new ParameterMetadataImpl( domainParameterXref.getQueryParameters() );
|
||||
|
||||
}
|
||||
|
||||
if ( stats ) {
|
||||
|
|
|
@ -80,15 +80,23 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
|
|||
Key key,
|
||||
Supplier<SelectQueryPlan<R>> creator) {
|
||||
log.tracef( "QueryPlan#getSelectQueryPlan(%s)", key );
|
||||
final StatisticsImplementor statistics = statisticsSupplier.get();
|
||||
final boolean stats = statistics.isStatisticsEnabled();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final SelectQueryPlan<R> cached = (SelectQueryPlan<R>) queryPlanCache.get( key );
|
||||
if ( cached != null ) {
|
||||
if ( stats ) {
|
||||
statistics.queryPlanCacheHit( key.getQueryString() );
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
final SelectQueryPlan<R> plan = creator.get();
|
||||
queryPlanCache.put( key.prepareForStore(), plan );
|
||||
if ( stats ) {
|
||||
statistics.queryPlanCacheMiss( key.getQueryString() );
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.query.results;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.metamodel.EntityType;
|
||||
|
@ -13,7 +15,6 @@ import jakarta.persistence.metamodel.SingularAttribute;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.RuntimeMetamodels;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
|
@ -38,6 +39,7 @@ import org.hibernate.query.results.implicit.ImplicitFetchBuilder;
|
|||
import org.hibernate.query.results.implicit.ImplicitFetchBuilderBasic;
|
||||
import org.hibernate.query.results.implicit.ImplicitFetchBuilderEmbeddable;
|
||||
import org.hibernate.query.results.implicit.ImplicitFetchBuilderEntity;
|
||||
import org.hibernate.query.results.implicit.ImplicitFetchBuilderEntityPart;
|
||||
import org.hibernate.query.results.implicit.ImplicitFetchBuilderPlural;
|
||||
import org.hibernate.query.results.implicit.ImplicitModelPartResultBuilderEntity;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
@ -236,7 +238,7 @@ public class Builders {
|
|||
}
|
||||
|
||||
public static DynamicFetchBuilderLegacy fetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
|
||||
return new DynamicFetchBuilderLegacy( tableAlias, ownerTableAlias, joinPropertyName, null, null );
|
||||
return new DynamicFetchBuilderLegacy( tableAlias, ownerTableAlias, joinPropertyName, new ArrayList<>(), new HashMap<>() );
|
||||
}
|
||||
|
||||
public static ResultBuilder implicitEntityResultBuilder(
|
||||
|
@ -273,15 +275,7 @@ public class Builders {
|
|||
}
|
||||
|
||||
if ( fetchable instanceof EntityCollectionPart ) {
|
||||
final EntityCollectionPart entityCollectionPart = (EntityCollectionPart) fetchable;
|
||||
return (parent, fetchablePath, jdbcResultsMetadata, legacyFetchResolver, domainResultCreationState) -> parent.generateFetchableFetch(
|
||||
entityCollectionPart,
|
||||
fetchablePath,
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
null,
|
||||
domainResultCreationState
|
||||
);
|
||||
return new ImplicitFetchBuilderEntityPart( fetchPath, (EntityCollectionPart) fetchable );
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -35,4 +35,6 @@ public interface FetchBuilder {
|
|||
|
||||
default void visitFetchBuilders(BiConsumer<String, FetchBuilder> consumer) {
|
||||
}
|
||||
|
||||
FetchBuilder cacheKeyInstance();
|
||||
}
|
||||
|
|
|
@ -32,6 +32,11 @@ public class ImplicitAttributeFetchBuilder implements FetchBuilder, ImplicitFetc
|
|||
this.attributeMapping = attributeMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
|
@ -50,4 +55,25 @@ public class ImplicitAttributeFetchBuilder implements FetchBuilder, ImplicitFetc
|
|||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ImplicitAttributeFetchBuilder that = (ImplicitAttributeFetchBuilder) o;
|
||||
return navigablePath.equals( that.navigablePath )
|
||||
&& attributeMapping.equals( that.attributeMapping );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + attributeMapping.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ public interface ResultBuilder {
|
|||
|
||||
Class<?> getJavaType();
|
||||
|
||||
ResultBuilder cacheKeyInstance();
|
||||
|
||||
default void visitFetchBuilders(BiConsumer<String, FetchBuilder> consumer) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -37,6 +38,7 @@ import org.hibernate.sql.results.graph.basic.BasicResult;
|
|||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
||||
|
@ -47,12 +49,46 @@ import org.hibernate.type.BasicType;
|
|||
@Internal
|
||||
public class ResultSetMappingImpl implements ResultSetMapping {
|
||||
private final String mappingIdentifier;
|
||||
|
||||
private final boolean isDynamic;
|
||||
private List<ResultBuilder> resultBuilders;
|
||||
private Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders;
|
||||
|
||||
public ResultSetMappingImpl(String mappingIdentifier) {
|
||||
this( mappingIdentifier, false );
|
||||
}
|
||||
|
||||
public ResultSetMappingImpl(String mappingIdentifier, boolean isDynamic) {
|
||||
this.mappingIdentifier = mappingIdentifier;
|
||||
this.isDynamic = isDynamic;
|
||||
}
|
||||
|
||||
private ResultSetMappingImpl(ResultSetMappingImpl original) {
|
||||
this.mappingIdentifier = original.mappingIdentifier;
|
||||
this.isDynamic = original.isDynamic;
|
||||
if ( !original.isDynamic || original.resultBuilders == null ) {
|
||||
this.resultBuilders = null;
|
||||
}
|
||||
else {
|
||||
final List<ResultBuilder> resultBuilders = new ArrayList<>( original.resultBuilders.size() );
|
||||
for ( ResultBuilder resultBuilder : original.resultBuilders ) {
|
||||
resultBuilders.add( resultBuilder.cacheKeyInstance() );
|
||||
}
|
||||
this.resultBuilders = resultBuilders;
|
||||
}
|
||||
if ( !original.isDynamic || original.legacyFetchBuilders == null ) {
|
||||
this.legacyFetchBuilders = null;
|
||||
}
|
||||
else {
|
||||
final Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders = new HashMap<>( original.legacyFetchBuilders.size() );
|
||||
for ( Map.Entry<String, Map<String, DynamicFetchBuilderLegacy>> entry : original.legacyFetchBuilders.entrySet() ) {
|
||||
final Map<String, DynamicFetchBuilderLegacy> newValue = new HashMap<>( entry.getValue().size() );
|
||||
for ( Map.Entry<String, DynamicFetchBuilderLegacy> builderEntry : entry.getValue().entrySet() ) {
|
||||
newValue.put( builderEntry.getKey(), builderEntry.getValue().cacheKeyInstance() );
|
||||
}
|
||||
legacyFetchBuilders.put( entry.getKey(), newValue );
|
||||
}
|
||||
this.legacyFetchBuilders = legacyFetchBuilders;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -306,4 +342,43 @@ public class ResultSetMappingImpl implements ResultSetMapping {
|
|||
public NamedResultSetMappingMemento toMemento(String name) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcValuesMappingProducer cacheKeyInstance() {
|
||||
return new ResultSetMappingImpl( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if ( isDynamic ) {
|
||||
int result = mappingIdentifier != null ? mappingIdentifier.hashCode() : 0;
|
||||
result = 31 * result + ( resultBuilders != null ? resultBuilders.hashCode() : 0 );
|
||||
result = 31 * result + ( legacyFetchBuilders != null ? legacyFetchBuilders.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return mappingIdentifier.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ResultSetMappingImpl that = (ResultSetMappingImpl) o;
|
||||
if ( isDynamic ) {
|
||||
return that.isDynamic
|
||||
&& Objects.equals( mappingIdentifier, that.mappingIdentifier )
|
||||
&& Objects.equals( resultBuilders, that.resultBuilders )
|
||||
&& Objects.equals( legacyFetchBuilders, that.legacyFetchBuilders );
|
||||
}
|
||||
else {
|
||||
return !that.isDynamic && mappingIdentifier.equals( that.mappingIdentifier );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.results.complete;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
|
@ -13,6 +14,7 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
|||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.BasicValuedFetchBuilder;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.MissingSqlSelectionException;
|
||||
import org.hibernate.query.results.PositionalSelectionsNotAllowedException;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
|
@ -45,6 +47,11 @@ public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder, Basi
|
|||
this.selectionAlias = selectionAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
|
@ -113,4 +120,27 @@ public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder, Basi
|
|||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CompleteFetchBuilderBasicPart that = (CompleteFetchBuilderBasicPart) o;
|
||||
return navigablePath.equals( that.navigablePath )
|
||||
&& referencedModelPart.equals( that.referencedModelPart )
|
||||
&& Objects.equals( selectionAlias, that.selectionAlias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + referencedModelPart.hashCode();
|
||||
result = 31 * result + ( selectionAlias != null ? selectionAlias.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.function.BiFunction;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
|
@ -46,6 +47,15 @@ public class CompleteFetchBuilderEntityValuedModelPart
|
|||
this.columnAliases = columnAliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return new CompleteFetchBuilderEntityValuedModelPart(
|
||||
navigablePath,
|
||||
modelPart,
|
||||
List.copyOf( columnAliases )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
|
@ -97,4 +107,26 @@ public class CompleteFetchBuilderEntityValuedModelPart
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CompleteFetchBuilderEntityValuedModelPart that = (CompleteFetchBuilderEntityValuedModelPart) o;
|
||||
return navigablePath.equals( that.navigablePath )
|
||||
&& modelPart.equals( that.modelPart )
|
||||
&& columnAliases.equals( that.columnAliases );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + modelPart.hashCode();
|
||||
result = 31 * result + columnAliases.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.function.BiFunction;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
|
@ -59,6 +60,11 @@ public class CompleteResultBuilderBasicModelPart
|
|||
return modelPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -91,4 +97,32 @@ public class CompleteResultBuilderBasicModelPart
|
|||
modelPart.getJavaTypeDescriptor()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CompleteResultBuilderBasicModelPart that = (CompleteResultBuilderBasicModelPart) o;
|
||||
|
||||
if ( !navigablePath.equals( that.navigablePath ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !modelPart.equals( that.modelPart ) ) {
|
||||
return false;
|
||||
}
|
||||
return columnAlias.equals( that.columnAlias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + modelPart.hashCode();
|
||||
result = 31 * result + columnAlias.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
*/
|
||||
package org.hibernate.query.results.complete;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
|
@ -37,10 +39,8 @@ import static org.hibernate.query.results.ResultsHelper.impl;
|
|||
*/
|
||||
public class CompleteResultBuilderBasicValuedConverted<O,R> implements CompleteResultBuilderBasicValued {
|
||||
private final String explicitColumnName;
|
||||
private final ManagedBean<? extends AttributeConverter<O, R>> converterBean;
|
||||
private final JavaType<? extends AttributeConverter<O, R>> converterJtd;
|
||||
private final BasicJavaType<O> domainJavaType;
|
||||
private final BasicValuedMapping underlyingMapping;
|
||||
private final JpaAttributeConverterImpl<O, R> valueConverter;
|
||||
|
||||
public CompleteResultBuilderBasicValuedConverted(
|
||||
String explicitColumnName,
|
||||
|
@ -49,15 +49,23 @@ public class CompleteResultBuilderBasicValuedConverted<O,R> implements CompleteR
|
|||
BasicJavaType<O> domainJavaType,
|
||||
BasicValuedMapping underlyingMapping) {
|
||||
this.explicitColumnName = explicitColumnName;
|
||||
this.converterBean = converterBean;
|
||||
this.converterJtd = converterJtd;
|
||||
this.domainJavaType = domainJavaType;
|
||||
this.underlyingMapping = underlyingMapping;
|
||||
this.valueConverter = new JpaAttributeConverterImpl<>(
|
||||
converterBean,
|
||||
converterJtd,
|
||||
domainJavaType,
|
||||
underlyingMapping.getJdbcMapping().getJavaTypeDescriptor()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return domainJavaType.getJavaTypeClass();
|
||||
return valueConverter.getDomainJavaDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,22 +131,43 @@ public class CompleteResultBuilderBasicValuedConverted<O,R> implements CompleteR
|
|||
return new SqlSelectionImpl( valuesArrayPosition, underlyingMapping );
|
||||
}
|
||||
),
|
||||
domainJavaType,
|
||||
valueConverter.getDomainJavaDescriptor(),
|
||||
sessionFactory.getTypeConfiguration()
|
||||
);
|
||||
|
||||
final JpaAttributeConverterImpl<O,R> valueConverter = new JpaAttributeConverterImpl<>(
|
||||
converterBean,
|
||||
converterJtd,
|
||||
domainJavaType,
|
||||
underlyingMapping.getJdbcMapping().getJavaTypeDescriptor()
|
||||
);
|
||||
|
||||
return new BasicResult<>(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
columnName,
|
||||
domainJavaType,
|
||||
valueConverter.getDomainJavaDescriptor(),
|
||||
valueConverter
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CompleteResultBuilderBasicValuedConverted<?, ?> that = (CompleteResultBuilderBasicValuedConverted<?, ?>) o;
|
||||
|
||||
if ( !Objects.equals( explicitColumnName, that.explicitColumnName ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !underlyingMapping.equals( that.underlyingMapping ) ) {
|
||||
return false;
|
||||
}
|
||||
return valueConverter.equals( that.valueConverter );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = explicitColumnName != null ? explicitColumnName.hashCode() : 0;
|
||||
result = 31 * result + underlyingMapping.hashCode();
|
||||
result = 31 * result + valueConverter.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
*/
|
||||
package org.hibernate.query.results.complete;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
|
@ -52,6 +54,11 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
|
|||
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return explicitJavaTypeDescriptor.getJavaTypeClass();
|
||||
|
@ -142,4 +149,31 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CompleteResultBuilderBasicValuedStandard that = (CompleteResultBuilderBasicValuedStandard) o;
|
||||
|
||||
if ( !Objects.equals( explicitColumnName, that.explicitColumnName ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !Objects.equals( explicitType, that.explicitType ) ) {
|
||||
return false;
|
||||
}
|
||||
return explicitJavaTypeDescriptor.equals( that.explicitJavaTypeDescriptor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = explicitColumnName != null ? explicitColumnName.hashCode() : 0;
|
||||
result = 31 * result + ( explicitType != null ? explicitType.hashCode() : 0 );
|
||||
result = 31 * result + explicitJavaTypeDescriptor.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.results.complete;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -19,6 +20,7 @@ import org.hibernate.query.NativeQuery;
|
|||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FromClauseAccessImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
|
@ -84,6 +86,11 @@ public class CompleteResultBuilderCollectionStandard implements CompleteResultBu
|
|||
return navigablePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -174,4 +181,32 @@ public class CompleteResultBuilderCollectionStandard implements CompleteResultBu
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CompleteResultBuilderCollectionStandard that = (CompleteResultBuilderCollectionStandard) o;
|
||||
return tableAlias.equals( that.tableAlias )
|
||||
&& navigablePath.equals( that.navigablePath )
|
||||
&& pluralAttributeDescriptor.equals( that.pluralAttributeDescriptor )
|
||||
&& Arrays.equals( keyColumnNames, that.keyColumnNames )
|
||||
&& Arrays.equals( indexColumnNames, that.indexColumnNames )
|
||||
&& Arrays.equals( elementColumnNames, that.elementColumnNames );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = tableAlias.hashCode();
|
||||
result = 31 * result + navigablePath.hashCode();
|
||||
result = 31 * result + pluralAttributeDescriptor.hashCode();
|
||||
result = 31 * result + Arrays.hashCode( keyColumnNames );
|
||||
result = 31 * result + Arrays.hashCode( indexColumnNames );
|
||||
result = 31 * result + Arrays.hashCode( elementColumnNames );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.results.complete;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
|
@ -17,6 +18,7 @@ import org.hibernate.query.NavigablePath;
|
|||
import org.hibernate.query.results.BasicValuedFetchBuilder;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
@ -77,6 +79,11 @@ public class CompleteResultBuilderEntityJpa implements CompleteResultBuilderEnti
|
|||
return entityDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -133,4 +140,31 @@ public class CompleteResultBuilderEntityJpa implements CompleteResultBuilderEnti
|
|||
public void visitFetchBuilders(BiConsumer<String, FetchBuilder> consumer) {
|
||||
explicitFetchBuilderMap.forEach( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + entityDescriptor.hashCode();
|
||||
result = 31 * result + lockMode.hashCode();
|
||||
result = 31 * result + ( discriminatorFetchBuilder != null ? discriminatorFetchBuilder.hashCode() : 0 );
|
||||
result = 31 * result + explicitFetchBuilderMap.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CompleteResultBuilderEntityJpa that = (CompleteResultBuilderEntityJpa) o;
|
||||
return navigablePath.equals( that.navigablePath )
|
||||
&& entityDescriptor.equals( that.entityDescriptor )
|
||||
&& lockMode == that.lockMode
|
||||
&& Objects.equals( discriminatorFetchBuilder, that.discriminatorFetchBuilder )
|
||||
&& explicitFetchBuilderMap.equals( that.explicitFetchBuilderMap );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.results.complete;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
|
@ -18,6 +19,7 @@ import org.hibernate.query.NavigablePath;
|
|||
import org.hibernate.query.results.BasicValuedFetchBuilder;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
@ -105,6 +107,11 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -161,4 +168,31 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
|||
public void visitFetchBuilders(BiConsumer<String, FetchBuilder> consumer) {
|
||||
explicitFetchBuilderMap.forEach( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + entityDescriptor.hashCode();
|
||||
result = 31 * result + lockMode.hashCode();
|
||||
result = 31 * result + ( discriminatorFetchBuilder != null ? discriminatorFetchBuilder.hashCode() : 0 );
|
||||
result = 31 * result + explicitFetchBuilderMap.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CompleteResultBuilderEntityStandard that = (CompleteResultBuilderEntityStandard) o;
|
||||
return navigablePath.equals( that.navigablePath )
|
||||
&& entityDescriptor.equals( that.entityDescriptor )
|
||||
&& lockMode == that.lockMode
|
||||
&& Objects.equals( discriminatorFetchBuilder, that.discriminatorFetchBuilder )
|
||||
&& explicitFetchBuilderMap.equals( that.explicitFetchBuilderMap );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,11 @@ public class CompleteResultBuilderInstantiation
|
|||
return javaTypeDescriptor.getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -74,4 +79,25 @@ public class CompleteResultBuilderInstantiation
|
|||
argumentDomainResults
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CompleteResultBuilderInstantiation that = (CompleteResultBuilderInstantiation) o;
|
||||
return javaTypeDescriptor.equals( that.javaTypeDescriptor )
|
||||
&& argumentResultBuilders.equals( that.argumentResultBuilders );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = javaTypeDescriptor.hashCode();
|
||||
result = 31 * result + argumentResultBuilders.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.engine.FetchTiming;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.BasicValuedFetchBuilder;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
|
@ -36,6 +37,11 @@ public class DelayedFetchBuilderBasicPart
|
|||
this.isEnhancedForLazyLoading = isEnhancedForLazyLoading;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
|
@ -64,4 +70,27 @@ public class DelayedFetchBuilderBasicPart
|
|||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DelayedFetchBuilderBasicPart that = (DelayedFetchBuilderBasicPart) o;
|
||||
return isEnhancedForLazyLoading == that.isEnhancedForLazyLoading
|
||||
&& navigablePath.equals( that.navigablePath )
|
||||
&& referencedModelPart.equals( that.referencedModelPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + referencedModelPart.hashCode();
|
||||
result = 31 * result + ( isEnhancedForLazyLoading ? 1 : 0 );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.results.dynamic;
|
|||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
|
@ -20,6 +21,26 @@ public abstract class AbstractFetchBuilderContainer<T extends AbstractFetchBuild
|
|||
implements DynamicFetchBuilderContainer {
|
||||
private Map<String, DynamicFetchBuilder> fetchBuilderMap;
|
||||
|
||||
protected AbstractFetchBuilderContainer() {
|
||||
}
|
||||
|
||||
protected AbstractFetchBuilderContainer(AbstractFetchBuilderContainer<T> original) {
|
||||
if ( original.fetchBuilderMap != null ) {
|
||||
final Map<String, DynamicFetchBuilder> fetchBuilderMap = new HashMap<>( original.fetchBuilderMap.size() );
|
||||
for ( Map.Entry<String, DynamicFetchBuilder> entry : original.fetchBuilderMap.entrySet() ) {
|
||||
final DynamicFetchBuilder fetchBuilder;
|
||||
if ( entry.getValue() instanceof DynamicFetchBuilderStandard ) {
|
||||
fetchBuilder = ( (DynamicFetchBuilderStandard) entry.getValue() ).cacheKeyInstance( this );
|
||||
}
|
||||
else {
|
||||
fetchBuilder = entry.getValue().cacheKeyInstance();
|
||||
}
|
||||
fetchBuilderMap.put( entry.getKey(), fetchBuilder );
|
||||
}
|
||||
this.fetchBuilderMap = fetchBuilderMap;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getPropertyBase();
|
||||
|
||||
@Override
|
||||
|
@ -79,4 +100,22 @@ public abstract class AbstractFetchBuilderContainer<T extends AbstractFetchBuild
|
|||
}
|
||||
fetchBuilderMap.put( propertyName, fetchBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final AbstractFetchBuilderContainer<?> that = (AbstractFetchBuilderContainer<?>) o;
|
||||
return Objects.equals( fetchBuilderMap, that.fetchBuilderMap );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return fetchBuilderMap != null ? fetchBuilderMap.hashCode() : 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,5 +16,7 @@ import org.hibernate.sql.results.graph.Fetchable;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DynamicFetchBuilder extends FetchBuilder, NativeQuery.ReturnProperty {
|
||||
DynamicFetchBuilder cacheKeyInstance();
|
||||
|
||||
List<String> getColumnAliases();
|
||||
}
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.query.results.dynamic;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
|
@ -59,12 +61,7 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
|||
String fetchableName,
|
||||
List<String> columnNames,
|
||||
Map<String, FetchBuilder> fetchBuilderMap) {
|
||||
this.tableAlias = tableAlias;
|
||||
this.ownerTableAlias = ownerTableAlias;
|
||||
this.fetchableName = fetchableName;
|
||||
this.columnNames = columnNames;
|
||||
this.fetchBuilderMap = fetchBuilderMap;
|
||||
this.resultBuilderEntity = null;
|
||||
this( tableAlias, ownerTableAlias, fetchableName, columnNames, fetchBuilderMap, null );
|
||||
}
|
||||
|
||||
public DynamicFetchBuilderLegacy(
|
||||
|
@ -97,6 +94,28 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
|||
return fetchableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicFetchBuilderLegacy cacheKeyInstance() {
|
||||
final Map<String, FetchBuilder> fetchBuilderMap;
|
||||
if ( this.fetchBuilderMap == null ) {
|
||||
fetchBuilderMap = null;
|
||||
}
|
||||
else {
|
||||
fetchBuilderMap = new HashMap<>( this.fetchBuilderMap.size() );
|
||||
for ( Map.Entry<String, FetchBuilder> entry : this.fetchBuilderMap.entrySet() ) {
|
||||
fetchBuilderMap.put( entry.getKey(), entry.getValue().cacheKeyInstance() );
|
||||
}
|
||||
}
|
||||
return new DynamicFetchBuilderLegacy(
|
||||
tableAlias,
|
||||
ownerTableAlias,
|
||||
fetchableName,
|
||||
List.copyOf( columnNames ),
|
||||
fetchBuilderMap,
|
||||
resultBuilderEntity == null ? null : resultBuilderEntity.cacheKeyInstance()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
|
@ -233,4 +252,33 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
|||
public void visitFetchBuilders(BiConsumer<String, FetchBuilder> consumer) {
|
||||
fetchBuilderMap.forEach( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DynamicFetchBuilderLegacy that = (DynamicFetchBuilderLegacy) o;
|
||||
return tableAlias.equals( that.tableAlias )
|
||||
&& ownerTableAlias.equals( that.ownerTableAlias )
|
||||
&& fetchableName.equals( that.fetchableName )
|
||||
&& Objects.equals( columnNames, that.columnNames )
|
||||
&& Objects.equals( fetchBuilderMap, that.fetchBuilderMap )
|
||||
&& Objects.equals( resultBuilderEntity, that.resultBuilderEntity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = tableAlias.hashCode();
|
||||
result = 31 * result + ownerTableAlias.hashCode();
|
||||
result = 31 * result + fetchableName.hashCode();
|
||||
result = 31 * result + ( columnNames != null ? columnNames.hashCode() : 0 );
|
||||
result = 31 * result + ( fetchBuilderMap != null ? fetchBuilderMap.hashCode() : 0 );
|
||||
result = 31 * result + ( resultBuilderEntity != null ? resultBuilderEntity.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
|||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
|
@ -41,13 +42,40 @@ public class DynamicFetchBuilderStandard
|
|||
private final DynamicFetchBuilderContainer container;
|
||||
private final String fetchableName;
|
||||
|
||||
private final List<String> columnNames = new ArrayList<>();
|
||||
private final List<String> columnNames;
|
||||
|
||||
public DynamicFetchBuilderStandard(
|
||||
DynamicFetchBuilderContainer container,
|
||||
String fetchableName) {
|
||||
this.container = container;
|
||||
this.fetchableName = fetchableName;
|
||||
this.columnNames = new ArrayList<>();
|
||||
}
|
||||
|
||||
private DynamicFetchBuilderStandard(
|
||||
DynamicFetchBuilderContainer container,
|
||||
String fetchableName,
|
||||
List<String> columnNames) {
|
||||
this.container = container;
|
||||
this.fetchableName = fetchableName;
|
||||
this.columnNames = columnNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicFetchBuilderStandard cacheKeyInstance() {
|
||||
return new DynamicFetchBuilderStandard(
|
||||
container,
|
||||
fetchableName,
|
||||
List.copyOf( columnNames )
|
||||
);
|
||||
}
|
||||
|
||||
public DynamicFetchBuilderStandard cacheKeyInstance(DynamicFetchBuilderContainer container) {
|
||||
return new DynamicFetchBuilderStandard(
|
||||
container,
|
||||
fetchableName,
|
||||
List.copyOf( columnNames )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -134,4 +162,25 @@ public class DynamicFetchBuilderStandard
|
|||
public List<String> getColumnAliases() {
|
||||
return columnNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fetchableName.hashCode();
|
||||
result = 31 * result + columnNames.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DynamicFetchBuilderStandard that = (DynamicFetchBuilderStandard) o;
|
||||
return fetchableName.equals( that.fetchableName )
|
||||
&& columnNames.equals( that.columnNames );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,5 @@ import org.hibernate.query.results.ResultBuilder;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DynamicResultBuilder extends ResultBuilder, NativeQuery.ReturnableResultNode {
|
||||
DynamicResultBuilder cacheKeyInstance();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.function.BiFunction;
|
|||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
|
@ -65,6 +66,11 @@ public class DynamicResultBuilderAttribute implements DynamicResultBuilder, Nati
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicResultBuilderAttribute cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -97,4 +103,29 @@ public class DynamicResultBuilderAttribute implements DynamicResultBuilder, Nati
|
|||
attributeMapping.getValueConverter()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DynamicResultBuilderAttribute that = (DynamicResultBuilderAttribute) o;
|
||||
return attributeMapping.equals( that.attributeMapping )
|
||||
&& columnAlias.equals( that.columnAlias )
|
||||
&& entityName.equals( that.entityName )
|
||||
&& attributePath.equals( that.attributePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = attributeMapping.hashCode();
|
||||
result = 31 * result + columnAlias.hashCode();
|
||||
result = 31 * result + entityName.hashCode();
|
||||
result = 31 * result + attributePath.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.results.dynamic;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
|
@ -13,6 +14,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
|
@ -35,10 +37,6 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
*/
|
||||
public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBuilderBasic {
|
||||
private final String columnAlias;
|
||||
|
||||
private final JavaType<O> domainJtd;
|
||||
private final JavaType<R> jdbcJtd;
|
||||
|
||||
private final BasicValueConverter<O,R> basicValueConverter;
|
||||
|
||||
public DynamicResultBuilderBasicConverted(
|
||||
|
@ -49,20 +47,15 @@ public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBui
|
|||
SessionFactoryImplementor sessionFactory) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
|
||||
this.columnAlias = columnAlias;
|
||||
this.domainJtd = jtdRegistry.getDescriptor( domainJavaType );
|
||||
this.jdbcJtd = jtdRegistry.getDescriptor( jdbcJavaType );
|
||||
|
||||
|
||||
final JavaType<? extends AttributeConverter> converterJtd = jtdRegistry.getDescriptor( converter.getClass() );
|
||||
final JavaType<? extends AttributeConverter<O, R>> converterJtd = jtdRegistry.getDescriptor( converter.getClass() );
|
||||
final ManagedBean<? extends AttributeConverter<O,R>> bean = new ProvidedInstanceManagedBeanImpl<>( converter );
|
||||
|
||||
this.basicValueConverter = new JpaAttributeConverterImpl(
|
||||
this.columnAlias = columnAlias;
|
||||
this.basicValueConverter = new JpaAttributeConverterImpl<>(
|
||||
bean,
|
||||
converterJtd,
|
||||
domainJtd,
|
||||
jdbcJtd
|
||||
jtdRegistry.getDescriptor( domainJavaType ),
|
||||
jtdRegistry.getDescriptor( jdbcJavaType )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -70,31 +63,31 @@ public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBui
|
|||
String columnAlias,
|
||||
Class<O> domainJavaType,
|
||||
Class<R> jdbcJavaType,
|
||||
Class<? extends AttributeConverter<O,R>> converterJavaType,
|
||||
Class<? extends AttributeConverter<O, R>> converterJavaType,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final ManagedBeanRegistry beans = sessionFactory.getServiceRegistry().getService( ManagedBeanRegistry.class );
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
final JavaType<? extends AttributeConverter<O, R>> converterJtd = jtdRegistry.getDescriptor( converterJavaType );
|
||||
final ManagedBean<? extends AttributeConverter<O, R>> bean = beans.getBean( converterJavaType );
|
||||
|
||||
this.columnAlias = columnAlias;
|
||||
this.domainJtd = jtdRegistry.getDescriptor( domainJavaType );
|
||||
this.jdbcJtd = jtdRegistry.getDescriptor( jdbcJavaType );
|
||||
|
||||
|
||||
final JavaType<? extends AttributeConverter<O,R>> converterJtd = jtdRegistry.getDescriptor( converterJavaType );
|
||||
final ManagedBean<? extends AttributeConverter<O,R>> bean = beans.getBean( converterJavaType );
|
||||
|
||||
this.basicValueConverter = new JpaAttributeConverterImpl(
|
||||
this.basicValueConverter = new JpaAttributeConverterImpl<>(
|
||||
bean,
|
||||
converterJtd,
|
||||
domainJtd,
|
||||
jdbcJtd
|
||||
jtdRegistry.getDescriptor( domainJavaType ),
|
||||
jtdRegistry.getDescriptor( jdbcJavaType )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return domainJtd.getJavaTypeClass();
|
||||
return basicValueConverter.getDomainJavaDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicResultBuilderBasicConverted cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -134,10 +127,39 @@ public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBui
|
|||
return new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
|
||||
}
|
||||
),
|
||||
domainJtd,
|
||||
basicValueConverter.getDomainJavaDescriptor(),
|
||||
typeConfiguration
|
||||
);
|
||||
|
||||
return new BasicResult<>( sqlSelection.getValuesArrayPosition(), columnAlias, domainJtd, basicValueConverter );
|
||||
return new BasicResult<>(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
columnAlias,
|
||||
basicValueConverter.getDomainJavaDescriptor(),
|
||||
basicValueConverter
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DynamicResultBuilderBasicConverted<?, ?> that = (DynamicResultBuilderBasicConverted<?, ?>) o;
|
||||
|
||||
if ( !Objects.equals( columnAlias, that.columnAlias ) ) {
|
||||
return false;
|
||||
}
|
||||
return basicValueConverter.equals( that.basicValueConverter );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = columnAlias != null ? columnAlias.hashCode() : 0;
|
||||
result = 31 * result + basicValueConverter.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.query.results.dynamic;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
|
@ -107,6 +109,11 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
|
|||
return columnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicResultBuilderBasicStandard cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -166,4 +173,39 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
|
|||
return new BasicResult<>( sqlSelection.getValuesArrayPosition(), resultAlias, javaTypeDescriptor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DynamicResultBuilderBasicStandard that = (DynamicResultBuilderBasicStandard) o;
|
||||
|
||||
if ( columnPosition != that.columnPosition ) {
|
||||
return false;
|
||||
}
|
||||
if ( !columnName.equals( that.columnName ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !resultAlias.equals( that.resultAlias ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !Objects.equals( explicitType, that.explicitType ) ) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals( explicitJavaTypeDescriptor, that.explicitJavaTypeDescriptor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = columnName.hashCode();
|
||||
result = 31 * result + columnPosition;
|
||||
result = 31 * result + resultAlias.hashCode();
|
||||
result = 31 * result + ( explicitType != null ? explicitType.hashCode() : 0 );
|
||||
result = 31 * result + ( explicitJavaTypeDescriptor != null ? explicitJavaTypeDescriptor.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
|
|||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
@ -99,6 +100,11 @@ public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilde
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicResultBuilderEntityCalculated cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -130,4 +136,36 @@ public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilde
|
|||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DynamicResultBuilderEntityCalculated that = (DynamicResultBuilderEntityCalculated) o;
|
||||
|
||||
if ( !navigablePath.equals( that.navigablePath ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !entityMapping.equals( that.entityMapping ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !tableAlias.equals( that.tableAlias ) ) {
|
||||
return false;
|
||||
}
|
||||
return explicitLockMode == that.explicitLockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + entityMapping.hashCode();
|
||||
result = 31 * result + tableAlias.hashCode();
|
||||
result = 31 * result + ( explicitLockMode != null ? explicitLockMode.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.results.dynamic;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -22,6 +23,7 @@ import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping
|
|||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.TableGroupImpl;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
|
@ -72,6 +74,16 @@ public class DynamicResultBuilderEntityStandard
|
|||
this.tableAlias = tableAlias;
|
||||
}
|
||||
|
||||
private DynamicResultBuilderEntityStandard(DynamicResultBuilderEntityStandard original) {
|
||||
super( original );
|
||||
this.navigablePath = original.navigablePath;
|
||||
this.entityMapping = original.entityMapping;
|
||||
this.tableAlias = original.tableAlias;
|
||||
this.lockMode = original.lockMode;
|
||||
this.idColumnNames = original.idColumnNames == null ? null : List.copyOf( original.idColumnNames );
|
||||
this.discriminatorColumnName = original.discriminatorColumnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return entityMapping.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
|
@ -111,6 +123,11 @@ public class DynamicResultBuilderEntityStandard
|
|||
return entityMapping.getEntityName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicResultBuilderEntityStandard cacheKeyInstance() {
|
||||
return new DynamicResultBuilderEntityStandard( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -280,4 +297,35 @@ public class DynamicResultBuilderEntityStandard
|
|||
this.discriminatorColumnName = columnName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + navigablePath.hashCode();
|
||||
result = 31 * result + entityMapping.hashCode();
|
||||
result = 31 * result + tableAlias.hashCode();
|
||||
result = 31 * result + ( lockMode != null ? lockMode.hashCode() : 0 );
|
||||
result = 31 * result + ( idColumnNames != null ? idColumnNames.hashCode() : 0 );
|
||||
result = 31 * result + ( discriminatorColumnName != null ? discriminatorColumnName.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DynamicResultBuilderEntityStandard that = (DynamicResultBuilderEntityStandard) o;
|
||||
return navigablePath.equals( that.navigablePath )
|
||||
&& entityMapping.equals( that.entityMapping )
|
||||
&& tableAlias.equals( that.tableAlias )
|
||||
&& lockMode == that.lockMode
|
||||
&& Objects.equals( idColumnNames, that.idColumnNames )
|
||||
&& Objects.equals( discriminatorColumnName, that.discriminatorColumnName )
|
||||
&& super.equals( o );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.function.BiFunction;
|
|||
import org.hibernate.query.DynamicInstantiationNature;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.results.Builders;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultBuilderInstantiationValued;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
@ -35,13 +36,53 @@ public class DynamicResultBuilderInstantiation<J>
|
|||
this.argumentBuilder = argumentBuilder;
|
||||
this.resultAlias = resultAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InstantiationArgument that = (InstantiationArgument) o;
|
||||
|
||||
if ( !argumentBuilder.equals( that.argumentBuilder ) ) {
|
||||
return false;
|
||||
}
|
||||
return resultAlias.equals( that.resultAlias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = argumentBuilder.hashCode();
|
||||
result = 31 * result + resultAlias.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private final JavaType<J> javaTypeDescriptor;
|
||||
private final List<InstantiationArgument> argumentResultBuilders = new ArrayList<>();
|
||||
private final List<InstantiationArgument> argumentResultBuilders;
|
||||
|
||||
public DynamicResultBuilderInstantiation(JavaType<J> javaTypeDescriptor) {
|
||||
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||
this.argumentResultBuilders = new ArrayList<>();
|
||||
}
|
||||
|
||||
private DynamicResultBuilderInstantiation(DynamicResultBuilderInstantiation<J> original) {
|
||||
this.javaTypeDescriptor = original.javaTypeDescriptor;
|
||||
final List<InstantiationArgument> arguments = new ArrayList<>( original.argumentResultBuilders.size() );
|
||||
for ( InstantiationArgument argument : original.argumentResultBuilders ) {
|
||||
arguments.add(
|
||||
new InstantiationArgument(
|
||||
argument.argumentBuilder.cacheKeyInstance(),
|
||||
argument.resultAlias
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
this.argumentResultBuilders = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,6 +98,11 @@ public class DynamicResultBuilderInstantiation<J>
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicResultBuilderInstantiation cacheKeyInstance() {
|
||||
return new DynamicResultBuilderInstantiation( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -72,7 +118,7 @@ public class DynamicResultBuilderInstantiation<J>
|
|||
for ( int i = 0; i < argumentResultBuilders.size(); i++ ) {
|
||||
final InstantiationArgument argument = argumentResultBuilders.get( i );
|
||||
|
||||
final ArgumentDomainResult<?> argumentDomainResult = new ArgumentDomainResult(
|
||||
final ArgumentDomainResult<?> argumentDomainResult = new ArgumentDomainResult<>(
|
||||
argument.argumentBuilder.buildResult(
|
||||
jdbcResultsMetadata,
|
||||
i,
|
||||
|
@ -84,11 +130,35 @@ public class DynamicResultBuilderInstantiation<J>
|
|||
argumentDomainResults.add( argumentDomainResult );
|
||||
}
|
||||
|
||||
return new DynamicInstantiationResultImpl(
|
||||
return new DynamicInstantiationResultImpl<>(
|
||||
null,
|
||||
DynamicInstantiationNature.CLASS,
|
||||
javaTypeDescriptor,
|
||||
argumentDomainResults
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DynamicResultBuilderInstantiation<?> that = (DynamicResultBuilderInstantiation<?>) o;
|
||||
|
||||
if ( !javaTypeDescriptor.equals( that.javaTypeDescriptor ) ) {
|
||||
return false;
|
||||
}
|
||||
return argumentResultBuilders.equals( that.argumentResultBuilders );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = javaTypeDescriptor.hashCode();
|
||||
result = 31 * result + argumentResultBuilders.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
|||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.BasicValuedFetchBuilder;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
|
@ -41,6 +42,11 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder, BasicVal
|
|||
this.fetchable = fetchable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicFetch<?> buildFetch(
|
||||
FetchParent parent,
|
||||
|
@ -109,4 +115,25 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder, BasicVal
|
|||
public String toString() {
|
||||
return "ImplicitFetchBuilderBasic(" + fetchPath + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ImplicitFetchBuilderBasic that = (ImplicitFetchBuilderBasic) o;
|
||||
return fetchPath.equals( that.fetchPath )
|
||||
&& fetchable.equals( that.fetchable );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fetchPath.hashCode();
|
||||
result = 31 * result + fetchable.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.query.results.implicit;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -67,6 +69,27 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
|
|||
this.fetchBuilders = fetchBuilders;
|
||||
}
|
||||
|
||||
private ImplicitFetchBuilderEmbeddable(ImplicitFetchBuilderEmbeddable original) {
|
||||
this.fetchPath = original.fetchPath;
|
||||
this.fetchable = original.fetchable;
|
||||
final Map<NavigablePath, FetchBuilder> fetchBuilders;
|
||||
if ( original.fetchBuilders.isEmpty() ) {
|
||||
fetchBuilders = Collections.emptyMap();
|
||||
}
|
||||
else {
|
||||
fetchBuilders = new HashMap<>( original.fetchBuilders.size() );
|
||||
for ( Map.Entry<NavigablePath, FetchBuilder> entry : original.fetchBuilders.entrySet() ) {
|
||||
fetchBuilders.put( entry.getKey(), entry.getValue().cacheKeyInstance() );
|
||||
}
|
||||
}
|
||||
this.fetchBuilders = fetchBuilders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return new ImplicitFetchBuilderEmbeddable( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
|
@ -118,6 +141,29 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
|
|||
return fetch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ImplicitFetchBuilderEmbeddable that = (ImplicitFetchBuilderEmbeddable) o;
|
||||
return fetchPath.equals( that.fetchPath )
|
||||
&& fetchable.equals( that.fetchable )
|
||||
&& fetchBuilders.equals( that.fetchBuilders );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fetchPath.hashCode();
|
||||
result = 31 * result + fetchable.hashCode();
|
||||
result = 31 * result + fetchBuilders.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImplicitFetchBuilderEmbeddable(" + fetchPath + ")";
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.results.implicit;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -92,6 +93,27 @@ public class ImplicitFetchBuilderEntity implements ImplicitFetchBuilder {
|
|||
this.fetchBuilders = fetchBuilders;
|
||||
}
|
||||
|
||||
private ImplicitFetchBuilderEntity(ImplicitFetchBuilderEntity original) {
|
||||
this.fetchPath = original.fetchPath;
|
||||
this.fetchable = original.fetchable;
|
||||
final Map<NavigablePath, FetchBuilder> fetchBuilders;
|
||||
if ( original.fetchBuilders.isEmpty() ) {
|
||||
fetchBuilders = Collections.emptyMap();
|
||||
}
|
||||
else {
|
||||
fetchBuilders = new HashMap<>( original.fetchBuilders.size() );
|
||||
for ( Map.Entry<NavigablePath, FetchBuilder> entry : original.fetchBuilders.entrySet() ) {
|
||||
fetchBuilders.put( entry.getKey(), entry.getValue().cacheKeyInstance() );
|
||||
}
|
||||
}
|
||||
this.fetchBuilders = fetchBuilders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return new ImplicitFetchBuilderEntity( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
|
@ -126,6 +148,29 @@ public class ImplicitFetchBuilderEntity implements ImplicitFetchBuilder {
|
|||
fetchBuilders.forEach( (k, v) -> consumer.accept( k.getUnaliasedLocalName(), v ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ImplicitFetchBuilderEntity that = (ImplicitFetchBuilderEntity) o;
|
||||
return fetchPath.equals( that.fetchPath )
|
||||
&& fetchable.equals( that.fetchable )
|
||||
&& fetchBuilders.equals( that.fetchBuilders );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fetchPath.hashCode();
|
||||
result = 31 * result + fetchable.hashCode();
|
||||
result = 31 * result + fetchBuilders.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImplicitFetchBuilderEntity(" + fetchPath + ")";
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.query.results.implicit;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ImplicitFetchBuilderEntityPart implements ImplicitFetchBuilder {
|
||||
private final NavigablePath fetchPath;
|
||||
private final EntityCollectionPart fetchable;
|
||||
|
||||
public ImplicitFetchBuilderEntityPart(NavigablePath fetchPath, EntityCollectionPart fetchable) {
|
||||
this.fetchPath = fetchPath;
|
||||
this.fetchable = fetchable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
NavigablePath fetchPath,
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
DomainResultCreationState creationState) {
|
||||
return parent.generateFetchableFetch(
|
||||
fetchable,
|
||||
fetchPath,
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
null,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ImplicitFetchBuilderEntityPart that = (ImplicitFetchBuilderEntityPart) o;
|
||||
return fetchPath.equals( that.fetchPath )
|
||||
&& fetchable.equals( that.fetchable );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fetchPath.hashCode();
|
||||
result = 31 * result + fetchable.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImplicitFetchBuilderEntityPart(" + fetchPath + ")";
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import org.hibernate.engine.FetchTiming;
|
|||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
|
@ -35,6 +36,11 @@ public class ImplicitFetchBuilderPlural implements ImplicitFetchBuilder {
|
|||
this.fetchable = fetchable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
|
@ -56,6 +62,27 @@ public class ImplicitFetchBuilderPlural implements ImplicitFetchBuilder {
|
|||
return fetch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ImplicitFetchBuilderPlural that = (ImplicitFetchBuilderPlural) o;
|
||||
return fetchPath.equals( that.fetchPath )
|
||||
&& fetchable.equals( that.fetchable );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fetchPath.hashCode();
|
||||
result = 31 * result + fetchable.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImplicitFetchBuilderPlural(" + fetchPath + ")";
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.function.BiFunction;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultBuilderBasicValued;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
|
@ -37,6 +38,11 @@ public class ImplicitModelPartResultBuilderBasic
|
|||
return modelPart.getExpressableJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -50,4 +56,28 @@ public class ImplicitModelPartResultBuilderBasic
|
|||
.getTableGroup( navigablePath.getParent() );
|
||||
return (BasicResult<?>) modelPart.createDomainResult( navigablePath, tableGroup, null, domainResultCreationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ImplicitModelPartResultBuilderBasic that = (ImplicitModelPartResultBuilderBasic) o;
|
||||
|
||||
if ( !navigablePath.equals( that.navigablePath ) ) {
|
||||
return false;
|
||||
}
|
||||
return modelPart.equals( that.modelPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + modelPart.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.function.BiFunction;
|
|||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultBuilderEmbeddable;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
|
@ -42,6 +43,11 @@ public class ImplicitModelPartResultBuilderEmbeddable
|
|||
return modelPart.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbeddableResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -88,4 +94,25 @@ public class ImplicitModelPartResultBuilderEmbeddable
|
|||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ImplicitModelPartResultBuilderEmbeddable that = (ImplicitModelPartResultBuilderEmbeddable) o;
|
||||
return navigablePath.equals( that.navigablePath )
|
||||
&& modelPart.equals( that.modelPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + modelPart.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
|
|||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultBuilderEntityValued;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
|
@ -45,6 +46,11 @@ public class ImplicitModelPartResultBuilderEntity
|
|||
return modelPart.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
@ -80,4 +86,28 @@ public class ImplicitModelPartResultBuilderEntity
|
|||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ImplicitModelPartResultBuilderEntity that = (ImplicitModelPartResultBuilderEntity) o;
|
||||
|
||||
if ( !navigablePath.equals( that.navigablePath ) ) {
|
||||
return false;
|
||||
}
|
||||
return modelPart.equals( that.modelPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = navigablePath.hashCode();
|
||||
result = 31 * result + modelPart.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ public class NativeQueryImpl<R>
|
|||
session.isQueryParametersValidationEnabled()
|
||||
);
|
||||
|
||||
this.resultSetMapping = new ResultSetMappingImpl( sqlString );
|
||||
this.resultSetMapping = new ResultSetMappingImpl( sqlString, true );
|
||||
this.resultMappingSuppliedToCtor = false;
|
||||
}
|
||||
|
||||
|
@ -770,6 +770,7 @@ public class NativeQueryImpl<R>
|
|||
return new SelectInterpretationsKey(
|
||||
getQueryString(),
|
||||
resultSetMapping,
|
||||
getSynchronizedQuerySpaces(),
|
||||
getQueryOptions().getTupleTransformer(),
|
||||
getQueryOptions().getResultListTransformer()
|
||||
);
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
package org.hibernate.query.sql.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.hibernate.query.spi.QueryInterpretationCache;
|
||||
import org.hibernate.query.sqm.internal.SqmInterpretationsKey;
|
||||
|
||||
/**
|
||||
* QueryInterpretations key for non-select NativeQuery instances
|
||||
|
@ -21,11 +24,43 @@ public class NonSelectInterpretationsKey implements QueryInterpretationCache.Key
|
|||
|
||||
public NonSelectInterpretationsKey(String sql, Collection<String> querySpaces) {
|
||||
this.sql = sql;
|
||||
this.querySpaces = querySpaces;
|
||||
this.querySpaces = querySpaces == null ? Collections.emptySet() : querySpaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryInterpretationCache.Key prepareForStore() {
|
||||
return new NonSelectInterpretationsKey(
|
||||
sql,
|
||||
querySpaces.isEmpty() ? Collections.emptySet() : new HashSet<>( querySpaces )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NonSelectInterpretationsKey that = (NonSelectInterpretationsKey) o;
|
||||
|
||||
if ( !sql.equals( that.sql ) ) {
|
||||
return false;
|
||||
}
|
||||
return querySpaces.equals( that.querySpaces );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = sql.hashCode();
|
||||
result = 31 * result + querySpaces.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.query.sql.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.query.ResultListTransformer;
|
||||
|
@ -19,18 +21,38 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
|||
public class SelectInterpretationsKey implements QueryInterpretationCache.Key {
|
||||
private final String sql;
|
||||
private final JdbcValuesMappingProducer jdbcValuesMappingProducer;
|
||||
private final Collection<String> querySpaces;
|
||||
private final TupleTransformer tupleTransformer;
|
||||
private final ResultListTransformer resultListTransformer;
|
||||
private final int hash;
|
||||
|
||||
public SelectInterpretationsKey(
|
||||
String sql,
|
||||
JdbcValuesMappingProducer jdbcValuesMappingProducer,
|
||||
Collection<String> querySpaces,
|
||||
TupleTransformer tupleTransformer,
|
||||
ResultListTransformer resultListTransformer) {
|
||||
this.sql = sql;
|
||||
this.jdbcValuesMappingProducer = jdbcValuesMappingProducer;
|
||||
this.querySpaces = querySpaces;
|
||||
this.tupleTransformer = tupleTransformer;
|
||||
this.resultListTransformer = resultListTransformer;
|
||||
this.hash = generateHashCode();
|
||||
}
|
||||
|
||||
private SelectInterpretationsKey(
|
||||
String sql,
|
||||
JdbcValuesMappingProducer jdbcValuesMappingProducer,
|
||||
Collection<String> querySpaces,
|
||||
TupleTransformer tupleTransformer,
|
||||
ResultListTransformer resultListTransformer,
|
||||
int hash) {
|
||||
this.sql = sql;
|
||||
this.jdbcValuesMappingProducer = jdbcValuesMappingProducer;
|
||||
this.querySpaces = querySpaces;
|
||||
this.tupleTransformer = tupleTransformer;
|
||||
this.resultListTransformer = resultListTransformer;
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,6 +60,32 @@ public class SelectInterpretationsKey implements QueryInterpretationCache.Key {
|
|||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryInterpretationCache.Key prepareForStore() {
|
||||
return new SelectInterpretationsKey(
|
||||
sql,
|
||||
jdbcValuesMappingProducer.cacheKeyInstance(),
|
||||
new HashSet<>( querySpaces ),
|
||||
tupleTransformer,
|
||||
resultListTransformer,
|
||||
hash
|
||||
);
|
||||
}
|
||||
|
||||
private int generateHashCode() {
|
||||
int result = sql.hashCode();
|
||||
result = 31 * result + jdbcValuesMappingProducer.hashCode();
|
||||
result = 31 * result + ( querySpaces != null ? querySpaces.hashCode() : 0 );
|
||||
result = 31 * result + ( tupleTransformer != null ? tupleTransformer.hashCode() : 0 );
|
||||
result = 31 * result + ( resultListTransformer != null ? resultListTransformer.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
|
@ -47,21 +95,11 @@ public class SelectInterpretationsKey implements QueryInterpretationCache.Key {
|
|||
return false;
|
||||
}
|
||||
|
||||
SelectInterpretationsKey that = (SelectInterpretationsKey) o;
|
||||
|
||||
final SelectInterpretationsKey that = (SelectInterpretationsKey) o;
|
||||
return sql.equals( that.sql )
|
||||
&& Objects.equals( jdbcValuesMappingProducer, that.jdbcValuesMappingProducer )
|
||||
&& Objects.equals( querySpaces, that.querySpaces )
|
||||
&& Objects.equals( tupleTransformer, that.tupleTransformer )
|
||||
&& Objects.equals( resultListTransformer, that.resultListTransformer );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = sql.hashCode();
|
||||
result = 31 * result + jdbcValuesMappingProducer.hashCode();
|
||||
result = 31 * result + ( tupleTransformer != null ? tupleTransformer.hashCode() : 0 );
|
||||
result = 31 * result + ( resultListTransformer != null ? resultListTransformer.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,4 +39,7 @@ public interface JdbcValuesMappingProducer {
|
|||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
default JdbcValuesMappingProducer cacheKeyInstance() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,6 +202,10 @@ public class QueryStatisticsImpl implements QueryStatistics {
|
|||
planCacheHitCount.increment();
|
||||
}
|
||||
|
||||
void incrementPlanCacheMissCount() {
|
||||
planCacheMissCount.increment();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "QueryStatistics"
|
||||
+ "[query=" + query
|
||||
|
|
|
@ -767,11 +767,20 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void queryPlanCacheHit(String hql) {
|
||||
public void queryPlanCacheHit(String query) {
|
||||
queryPlanCacheHitCount.increment();
|
||||
|
||||
if ( hql != null ) {
|
||||
getQueryStatistics( hql ).incrementPlanCacheHitCount();
|
||||
if ( query != null ) {
|
||||
getQueryStatistics( query ).incrementPlanCacheHitCount();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPlanCacheMiss(String query) {
|
||||
queryPlanCacheMissCount.increment();
|
||||
|
||||
if ( query != null ) {
|
||||
getQueryStatistics( query ).incrementPlanCacheMissCount();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -251,9 +251,18 @@ public interface StatisticsImplementor extends Statistics, Service {
|
|||
/**
|
||||
* Callback indicating a get from the query plan cache resulted in a hit.
|
||||
*
|
||||
* @param hql The query
|
||||
* @param query The query
|
||||
*/
|
||||
default void queryPlanCacheHit(String hql) {
|
||||
default void queryPlanCacheHit(String query) {
|
||||
//For backward compatibility
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback indicating a get from the query plan cache resulted in a miss.
|
||||
*
|
||||
* @param query The query
|
||||
*/
|
||||
default void queryPlanCacheMiss(String query) {
|
||||
//For backward compatibility
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ import jakarta.persistence.Tuple;
|
|||
import jakarta.persistence.TypedQuery;
|
||||
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
import org.hibernate.stat.QueryStatistics;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
|
@ -51,8 +54,6 @@ public class QueryPlanCacheStatisticsTest {
|
|||
|
||||
@BeforeAll
|
||||
protected void afterEntityManagerFactoryBuilt(SessionFactoryScope scope) {
|
||||
statistics = scope.getSessionFactory().getStatistics();
|
||||
|
||||
scope.inTransaction( entityManager -> {
|
||||
for ( long i = 1; i <= 5; i++ ) {
|
||||
Employee employee = new Employee();
|
||||
|
@ -64,8 +65,10 @@ public class QueryPlanCacheStatisticsTest {
|
|||
|
||||
@BeforeEach
|
||||
protected void cleanup(SessionFactoryScope scope) {
|
||||
scope.getSessionFactory().getQueryEngine().getInterpretationCache().close();
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
statistics = sessionFactory.getStatistics();
|
||||
statistics.clear();
|
||||
sessionFactory.getQueryEngine().getInterpretationCache().close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -125,6 +128,24 @@ public class QueryPlanCacheStatisticsTest {
|
|||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-13077" )
|
||||
public void testCreateQueryHitCount(SessionFactoryScope scope) {
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
||||
QueryImplementor<Employee> query = entityManager.createQuery(
|
||||
"select e from Employee e", Employee.class );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
|
||||
List<Employee> employees = query.getResultList();
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is 2 because the previous cache miss was for the HqlInterpretation and this is for the plan
|
||||
assertEquals( 2, statistics.getQueryPlanCacheMissCount() );
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createQuery(
|
||||
|
@ -133,6 +154,40 @@ public class QueryPlanCacheStatisticsTest {
|
|||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 2, as now we got the query plan from the cache
|
||||
assertEquals( 2, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createQuery(
|
||||
"select e from Employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 2, as now we got the query plan from the cache
|
||||
assertEquals( 2, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 4, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-14632" )
|
||||
public void testCreateNativeQueryHitCount(SessionFactoryScope scope) {
|
||||
statistics.clear();
|
||||
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createNativeQuery(
|
||||
"select * from employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
|
@ -141,8 +196,8 @@ public class QueryPlanCacheStatisticsTest {
|
|||
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createQuery(
|
||||
"select e from Employee e", Employee.class )
|
||||
List<Employee> employees = entityManager.createNativeQuery(
|
||||
"select * from employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
@ -155,8 +210,8 @@ public class QueryPlanCacheStatisticsTest {
|
|||
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createQuery(
|
||||
"select e from Employee e", Employee.class )
|
||||
List<Employee> employees = entityManager.createNativeQuery(
|
||||
"select * from employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
@ -176,15 +231,20 @@ public class QueryPlanCacheStatisticsTest {
|
|||
statistics.clear();
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
||||
Employee employees = entityManager.createNamedQuery(
|
||||
"find_employee_by_name", Employee.class )
|
||||
.setParameter( "name", "Employee: 1" )
|
||||
.getSingleResult();
|
||||
Query<Employee> query = entityManager.createNamedQuery(
|
||||
"find_employee_by_name", Employee.class )
|
||||
.setParameter( "name", "Employee: 1" );
|
||||
|
||||
//The miss count is 0 because the plan was compiled when the EMF was built, and we cleared the Statistics
|
||||
assertEquals( 0, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count is 1 since we got the plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||
|
||||
Employee employees = query.getSingleResult();
|
||||
|
||||
//The miss count is 1 because the previous cache hit was for the HqlInterpretation and this is for the plan
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
@ -194,10 +254,11 @@ public class QueryPlanCacheStatisticsTest {
|
|||
.setParameter( "name", "Employee: 1" )
|
||||
.getSingleResult();
|
||||
|
||||
//The miss count is still 0 because the plan was compiled when the EMF was built, and we cleared the Statistics
|
||||
assertEquals( 0, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count is 2 since we got the plan from the cache twice
|
||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||
//The miss count is still 1 because the plan was compiled when the EMF was built, and we cleared the Statistics
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count is 3 since we got the plan from the cache twice,
|
||||
//but the second time we have a hit for the HqlInterpretation and one for the plan
|
||||
assertEquals( 3, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
}
|
||||
|
||||
|
@ -206,16 +267,21 @@ public class QueryPlanCacheStatisticsTest {
|
|||
public void testCreateQueryTupleHitCount(SessionFactoryScope scope) {
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
||||
List<Tuple> employees = entityManager.createQuery(
|
||||
"select e.id, e.name from Employee e", Tuple.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
QueryImplementor<Tuple> query = entityManager.createQuery(
|
||||
"select e.id, e.name from Employee e", Tuple.class );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
|
||||
List<Tuple> employees = query.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is 2 because the previous cache miss was for the HqlInterpretation and this is for the plan
|
||||
assertEquals( 2, statistics.getQueryPlanCacheMissCount() );
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
@ -226,10 +292,10 @@ public class QueryPlanCacheStatisticsTest {
|
|||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 1, as now we got the query plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The miss count is still 2, as now we got the query plan from the cache
|
||||
assertEquals( 2, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
scope.inTransaction( entityManager -> {
|
||||
|
@ -240,10 +306,10 @@ public class QueryPlanCacheStatisticsTest {
|
|||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 1, as now we got the query plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The miss count is still 2, as now we got the query plan from the cache
|
||||
assertEquals( 2, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||
assertEquals( 4, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
}
|
||||
|
||||
|
@ -253,13 +319,17 @@ public class QueryPlanCacheStatisticsTest {
|
|||
scope.inTransaction( entityManager -> {
|
||||
TypedQuery<Employee> typedQuery = entityManager.createQuery( "select e from Employee e", Employee.class );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
|
||||
List<Employee> employees = typedQuery.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
//The miss count is 2 because the previous cache miss was for the HqlInterpretation and this is for the plan
|
||||
assertEquals( 2, statistics.getQueryPlanCacheMissCount() );
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
|
||||
typedQuery.setLockMode( LockModeType.READ );
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
/*
|
||||
* 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.stat.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.NamedQuery;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-12855")
|
||||
public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
private Statistics statistics;
|
||||
|
||||
@Override
|
||||
public Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
Employee.class
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addConfigOptions(Map options) {
|
||||
options.put( Environment.GENERATE_STATISTICS, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterEntityManagerFactoryBuilt() {
|
||||
SessionFactory sessionFactory = entityManagerFactory().unwrap( SessionFactory.class );
|
||||
statistics = sessionFactory.getStatistics();
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
for ( long i = 1; i <= 5; i++ ) {
|
||||
if ( i % 3 == 0 ) {
|
||||
entityManager.flush();
|
||||
}
|
||||
Employee employee = new Employee();
|
||||
employee.setName( String.format( "Employee: %d", i ) );
|
||||
entityManager.persist( employee );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-14632" )
|
||||
public void testCreateNativeQueryHitCount() {
|
||||
statistics.clear();
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createNativeQuery(
|
||||
"select * from employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createNativeQuery(
|
||||
"select * from employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 1, as now we got the query plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createNativeQuery(
|
||||
"select * from employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 1, as now we got the query plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Employee")
|
||||
@Table(name = "employee")
|
||||
@NamedQuery(
|
||||
name = "find_employee_by_name",
|
||||
query = "select e from Employee e where e.name = :name"
|
||||
)
|
||||
public static class Employee {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue