mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-27 14:30:16 +00:00
perf work
This commit is contained in:
parent
2502f4c108
commit
6f77e0d261
@ -1255,9 +1255,7 @@ public void addUniquePropertyReference(String referencedClass, String propertyNa
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
public void addUniqueConstraints(Table table, List uniqueConstraints) {
|
public void addUniqueConstraints(Table table, List uniqueConstraints) {
|
||||||
List<UniqueConstraintHolder> constraintHolders = new ArrayList<>(
|
List<UniqueConstraintHolder> constraintHolders = new ArrayList<>( uniqueConstraints.size() );
|
||||||
CollectionHelper.determineProperSizing( uniqueConstraints.size() )
|
|
||||||
);
|
|
||||||
|
|
||||||
int keyNameBase = determineCurrentNumberOfUniqueConstraintHolders( table );
|
int keyNameBase = determineCurrentNumberOfUniqueConstraintHolders( table );
|
||||||
for ( String[] columns : ( List<String[]> ) uniqueConstraints ) {
|
for ( String[] columns : ( List<String[]> ) uniqueConstraints ) {
|
||||||
|
@ -781,7 +781,7 @@ public static List<UniqueConstraintHolder> buildUniqueConstraintHolders(UniqueCo
|
|||||||
result = java.util.Collections.emptyList();
|
result = java.util.Collections.emptyList();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = new ArrayList<UniqueConstraintHolder>( CollectionHelper.determineProperSizing( annotations.length ) );
|
result = CollectionHelper.arrayList( annotations.length );
|
||||||
for ( UniqueConstraint uc : annotations ) {
|
for ( UniqueConstraint uc : annotations ) {
|
||||||
result.add(
|
result.add(
|
||||||
new UniqueConstraintHolder()
|
new UniqueConstraintHolder()
|
||||||
|
@ -614,14 +614,13 @@ public <T> QueryImplementor<T> createQuery(String queryString, Class<T> resultCl
|
|||||||
try {
|
try {
|
||||||
final QueryEngine queryEngine = getFactory().getQueryEngine();
|
final QueryEngine queryEngine = getFactory().getQueryEngine();
|
||||||
final QueryInterpretationCache interpretationCache = queryEngine.getInterpretationCache();
|
final QueryInterpretationCache interpretationCache = queryEngine.getInterpretationCache();
|
||||||
final SqmStatement sqm = interpretationCache.resolveSqmStatement(
|
|
||||||
queryString,
|
|
||||||
s -> queryEngine.getHqlTranslator().interpret( queryString )
|
|
||||||
);
|
|
||||||
|
|
||||||
final QuerySqmImpl query = new QuerySqmImpl(
|
final QuerySqmImpl query = new QuerySqmImpl(
|
||||||
queryString,
|
queryString,
|
||||||
sqm,
|
interpretationCache.resolveHqlInterpretation(
|
||||||
|
queryString,
|
||||||
|
s -> queryEngine.getHqlTranslator().interpret( queryString )
|
||||||
|
),
|
||||||
resultClass,
|
resultClass,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
@ -886,7 +885,6 @@ public <T> QueryImplementor<T> createQuery(CriteriaQuery<T> criteriaQuery) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
return new QuerySqmImpl<>(
|
return new QuerySqmImpl<>(
|
||||||
"<criteria>",
|
|
||||||
(SqmStatement) criteriaQuery,
|
(SqmStatement) criteriaQuery,
|
||||||
criteriaQuery.getResultType(),
|
criteriaQuery.getResultType(),
|
||||||
this
|
this
|
||||||
@ -902,7 +900,6 @@ public QueryImplementor createQuery(CriteriaUpdate criteriaUpdate) {
|
|||||||
checkOpen();
|
checkOpen();
|
||||||
try {
|
try {
|
||||||
return new QuerySqmImpl<>(
|
return new QuerySqmImpl<>(
|
||||||
"<criteria>",
|
|
||||||
(SqmUpdateStatement) criteriaUpdate,
|
(SqmUpdateStatement) criteriaUpdate,
|
||||||
null,
|
null,
|
||||||
this
|
this
|
||||||
@ -918,7 +915,6 @@ public QueryImplementor createQuery(CriteriaDelete criteriaDelete) {
|
|||||||
checkOpen();
|
checkOpen();
|
||||||
try {
|
try {
|
||||||
return new QuerySqmImpl<>(
|
return new QuerySqmImpl<>(
|
||||||
"<criteria>",
|
|
||||||
(SqmDeleteStatement) criteriaDelete,
|
(SqmDeleteStatement) criteriaDelete,
|
||||||
null,
|
null,
|
||||||
this
|
this
|
||||||
|
@ -28,25 +28,13 @@ public static String toLoggableString(NavigableRole role) {
|
|||||||
return UNREFERENCED;
|
return UNREFERENCED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( role.isRoot() ) {
|
return role.getFullPath();
|
||||||
return StringHelper.collapse( role.getFullPath() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert role.getParent() != null;
|
|
||||||
return StringHelper.collapse( role.getParent().getFullPath() ) + '.' + role.getNavigableName();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toLoggableString(NavigablePath path) {
|
public static String toLoggableString(NavigablePath path) {
|
||||||
assert path != null;
|
assert path != null;
|
||||||
|
|
||||||
if ( path.isRoot() ) {
|
return path.getFullPath();
|
||||||
return StringHelper.collapse( path.getFullPath() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert path.getParent() != null;
|
|
||||||
return StringHelper.collapse( path.getParent().getFullPath() ) + '.' + path.getLocalName();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toLoggableString(NavigableRole role, Object key) {
|
public static String toLoggableString(NavigableRole role, Object key) {
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public final class CollectionHelper {
|
public final class CollectionHelper {
|
||||||
|
public static final int DEFAULT_LIST_CAPACITY = 10;
|
||||||
public static final int MINIMUM_INITIAL_CAPACITY = 16;
|
public static final int MINIMUM_INITIAL_CAPACITY = 16;
|
||||||
public static final float LOAD_FACTOR = 0.75f;
|
public static final float LOAD_FACTOR = 0.75f;
|
||||||
|
|
||||||
@ -178,8 +179,8 @@ public static <K, V> ConcurrentHashMap<K, V> concurrentMap(int expectedNumberOfE
|
|||||||
return new ConcurrentHashMap<K, V>( size, loadFactor );
|
return new ConcurrentHashMap<K, V>( size, loadFactor );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ArrayList<T> arrayList(int anticipatedSize) {
|
public static <T> ArrayList<T> arrayList(int expectedNumberOfElements) {
|
||||||
return new ArrayList<T>( anticipatedSize );
|
return new ArrayList<>( Math.max( expectedNumberOfElements + 1, DEFAULT_LIST_CAPACITY ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Set<T> makeCopy(Set<T> source) {
|
public static <T> Set<T> makeCopy(Set<T> source) {
|
||||||
|
@ -251,20 +251,35 @@ public void visitJdbcTypes(
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitDisassembledJdbcValues(
|
public void visitDisassembledJdbcValues(
|
||||||
Object value, Clause clause, JdbcValuesConsumer valuesConsumer, SharedSessionContractImplementor session) {
|
Object value,
|
||||||
|
Clause clause,
|
||||||
|
JdbcValuesConsumer valuesConsumer,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitJdbcValues(
|
public void visitJdbcValues(
|
||||||
Object value, Clause clause, JdbcValuesConsumer valuesConsumer, SharedSessionContractImplementor session) {
|
Object value,
|
||||||
|
Clause clause,
|
||||||
|
JdbcValuesConsumer valuesConsumer,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfAttributeMappings() {
|
||||||
|
return attributeMappings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfDeclaredAttributeMappings() {
|
||||||
|
return getNumberOfAttributeMappings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ManagedMappingType extends MappingType, FetchableContainer {
|
public interface ManagedMappingType extends MappingType, FetchableContainer {
|
||||||
|
int getNumberOfAttributeMappings();
|
||||||
|
int getNumberOfDeclaredAttributeMappings();
|
||||||
|
|
||||||
Collection<AttributeMapping> getAttributeMappings();
|
Collection<AttributeMapping> getAttributeMappings();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,6 +156,7 @@ public void applySqlSelections(
|
|||||||
@Override
|
@Override
|
||||||
public Fetch generateFetch(
|
public Fetch generateFetch(
|
||||||
FetchParent fetchParent,
|
FetchParent fetchParent,
|
||||||
|
NavigablePath fetchablePath,
|
||||||
FetchTiming fetchTiming,
|
FetchTiming fetchTiming,
|
||||||
boolean selected,
|
boolean selected,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
@ -173,6 +174,7 @@ public Fetch generateFetch(
|
|||||||
return new BasicFetch(
|
return new BasicFetch(
|
||||||
sqlSelection.getValuesArrayPosition(),
|
sqlSelection.getValuesArrayPosition(),
|
||||||
fetchParent,
|
fetchParent,
|
||||||
|
fetchablePath,
|
||||||
this,
|
this,
|
||||||
getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
||||||
getConverter(),
|
getConverter(),
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -15,6 +14,8 @@
|
|||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
@ -38,7 +39,6 @@
|
|||||||
import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.results.internal.domain.composite.CompositeFetch;
|
import org.hibernate.sql.results.internal.domain.composite.CompositeFetch;
|
||||||
import org.hibernate.sql.results.internal.domain.composite.CompositeResult;
|
import org.hibernate.sql.results.internal.domain.composite.CompositeResult;
|
||||||
@ -47,6 +47,7 @@
|
|||||||
import org.hibernate.sql.results.spi.Fetch;
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
import org.hibernate.sql.results.spi.FetchParent;
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
import org.hibernate.sql.results.spi.Fetchable;
|
import org.hibernate.sql.results.spi.Fetchable;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
@ -106,6 +107,23 @@ public List<String> getMappedColumnExpressions() {
|
|||||||
return Arrays.asList( attrColumnNames );
|
return Arrays.asList( attrColumnNames );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJdbcTypes(
|
||||||
|
Consumer<JdbcMapping> action,
|
||||||
|
Clause clause,
|
||||||
|
TypeConfiguration typeConfiguration) {
|
||||||
|
getEmbeddableTypeDescriptor().visitJdbcTypes( action, clause, typeConfiguration );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJdbcValues(
|
||||||
|
Object value,
|
||||||
|
Clause clause,
|
||||||
|
JdbcValuesConsumer valuesConsumer,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
getEmbeddableTypeDescriptor().visitJdbcValues( value, clause, valuesConsumer, session );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> DomainResult<T> createDomainResult(
|
public <T> DomainResult<T> createDomainResult(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
@ -132,13 +150,14 @@ public void applySqlSelections(
|
|||||||
@Override
|
@Override
|
||||||
public Fetch generateFetch(
|
public Fetch generateFetch(
|
||||||
FetchParent fetchParent,
|
FetchParent fetchParent,
|
||||||
|
NavigablePath fetchablePath,
|
||||||
FetchTiming fetchTiming,
|
FetchTiming fetchTiming,
|
||||||
boolean selected,
|
boolean selected,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
DomainResultCreationState creationState) {
|
DomainResultCreationState creationState) {
|
||||||
return new CompositeFetch(
|
return new CompositeFetch(
|
||||||
fetchParent.getNavigablePath().append( getFetchableName() ),
|
fetchablePath,
|
||||||
this,
|
this,
|
||||||
fetchParent,
|
fetchParent,
|
||||||
fetchTiming,
|
fetchTiming,
|
||||||
@ -152,7 +171,7 @@ public Expression toSqlExpression(
|
|||||||
Clause clause,
|
Clause clause,
|
||||||
SqmToSqlAstConverter walker,
|
SqmToSqlAstConverter walker,
|
||||||
SqlAstCreationState sqlAstCreationState) {
|
SqlAstCreationState sqlAstCreationState) {
|
||||||
final List<ColumnReference> columnReferences = new ArrayList<>();
|
final List<ColumnReference> columnReferences = CollectionHelper.arrayList( attrColumnNames.length );
|
||||||
final TableReference tableReference = tableGroup.resolveTableReference( getContainingTableExpression() );
|
final TableReference tableReference = tableGroup.resolveTableReference( getContainingTableExpression() );
|
||||||
|
|
||||||
getEmbeddableTypeDescriptor().visitJdbcTypes(
|
getEmbeddableTypeDescriptor().visitJdbcTypes(
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
@ -103,6 +104,7 @@
|
|||||||
import org.hibernate.internal.FilterHelper;
|
import org.hibernate.internal.FilterHelper;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.jdbc.Expectation;
|
import org.hibernate.jdbc.Expectation;
|
||||||
import org.hibernate.jdbc.Expectations;
|
import org.hibernate.jdbc.Expectations;
|
||||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||||
@ -5313,16 +5315,24 @@ public Object[] getPropertyValues(Object object) {
|
|||||||
return accessOptimizer.getPropertyValues( object );
|
return accessOptimizer.getPropertyValues( object );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final List<Object> values = new ArrayList<>();
|
final Object[] values = new Object[ getNumberOfAttributeMappings() ];
|
||||||
|
final AtomicInteger index = new AtomicInteger( 0 );
|
||||||
|
|
||||||
|
//noinspection Convert2Lambda
|
||||||
visitAttributeMappings(
|
visitAttributeMappings(
|
||||||
attributeMapping -> {
|
new Consumer<AttributeMapping>() {
|
||||||
final AttributeMetadata attributeMetadata = attributeMapping.getAttributeMetadataAccess()
|
@Override
|
||||||
.resolveAttributeMetadata( this );
|
public void accept(AttributeMapping mapping) {
|
||||||
values.add( attributeMetadata.getPropertyAccess().getGetter().get( object ) );
|
values[ index.getAndIncrement() ] = mapping.getAttributeMetadataAccess()
|
||||||
|
.resolveAttributeMetadata( AbstractEntityPersister.this )
|
||||||
|
.getPropertyAccess()
|
||||||
|
.getGetter()
|
||||||
|
.get( object );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return values.toArray();
|
|
||||||
|
return values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6040,6 +6050,7 @@ public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version,
|
|||||||
private EntityVersionMapping versionMapping;
|
private EntityVersionMapping versionMapping;
|
||||||
|
|
||||||
private SortedMap<String, AttributeMapping> declaredAttributeMappings = new TreeMap<>();
|
private SortedMap<String, AttributeMapping> declaredAttributeMappings = new TreeMap<>();
|
||||||
|
private Collection<AttributeMapping> attributeMappings;
|
||||||
|
|
||||||
private ReflectionOptimizer.AccessOptimizer accessOptimizer;
|
private ReflectionOptimizer.AccessOptimizer accessOptimizer;
|
||||||
|
|
||||||
@ -6079,7 +6090,7 @@ public void prepareMappingModel(MappingModelCreationProcess creationProcess) {
|
|||||||
|
|
||||||
final EntityMetamodel currentEntityMetamodel = this.getEntityMetamodel();
|
final EntityMetamodel currentEntityMetamodel = this.getEntityMetamodel();
|
||||||
|
|
||||||
int stateArrayPosition = superMappingType == null ? 0 : superMappingType.getAttributeMappings().size();
|
int stateArrayPosition = superMappingType == null ? 0 : superMappingType.getNumberOfAttributeMappings();
|
||||||
|
|
||||||
for ( int i = 0; i < currentEntityMetamodel.getPropertySpan(); i++ ) {
|
for ( int i = 0; i < currentEntityMetamodel.getPropertySpan(); i++ ) {
|
||||||
final NonIdentifierAttribute runtimeAttrDefinition = currentEntityMetamodel.getProperties()[i];
|
final NonIdentifierAttribute runtimeAttrDefinition = currentEntityMetamodel.getProperties()[i];
|
||||||
@ -6126,6 +6137,20 @@ public void linkWithSubType(EntityMappingType sub, MappingModelCreationProcess c
|
|||||||
subclassMappingTypes.put( sub.getEntityName(), sub );
|
subclassMappingTypes.put( sub.getEntityName(), sub );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfAttributeMappings() {
|
||||||
|
if ( attributeMappings == null ) {
|
||||||
|
// force calculation of `attributeMappings`
|
||||||
|
getAttributeMappings();
|
||||||
|
}
|
||||||
|
return attributeMappings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfDeclaredAttributeMappings() {
|
||||||
|
return declaredAttributeMappings.size();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTypeOrSuperType(EntityMappingType targetType) {
|
public boolean isTypeOrSuperType(EntityMappingType targetType) {
|
||||||
if ( targetType == null ) {
|
if ( targetType == null ) {
|
||||||
@ -6260,8 +6285,6 @@ public EntityVersionMapping getVersionMapping() {
|
|||||||
return versionMapping;
|
return versionMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<AttributeMapping> attributeMappings;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<AttributeMapping> getAttributeMappings() {
|
public Collection<AttributeMapping> getAttributeMappings() {
|
||||||
if ( attributeMappings == null ) {
|
if ( attributeMappings == null ) {
|
||||||
|
@ -118,6 +118,18 @@ default String getSqlAliasStem() {
|
|||||||
return SqlAliasStemHelper.INSTANCE.generateStemFromEntityName( getEntityName() );
|
return SqlAliasStemHelper.INSTANCE.generateStemFromEntityName( getEntityName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default int getNumberOfAttributeMappings() {
|
||||||
|
// for backwards-compatibility
|
||||||
|
return getAttributeMappings().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default int getNumberOfDeclaredAttributeMappings() {
|
||||||
|
// for backwards-compatibility
|
||||||
|
return getAttributeMappings().size();
|
||||||
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// stuff that is persister-centric and/or EntityInfo-centric ~~~~~~~~~~~~~~
|
// stuff that is persister-centric and/or EntityInfo-centric ~~~~~~~~~~~~~~
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
|
||||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
import static org.hibernate.internal.CoreLogging.messageLogger;
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ public GetterMethodImpl(Class containerClass, String propertyName, Method getter
|
|||||||
@Override
|
@Override
|
||||||
public Object get(Object owner) {
|
public Object get(Object owner) {
|
||||||
try {
|
try {
|
||||||
return getterMethod.invoke( owner );
|
return getterMethod.invoke( owner, ArrayHelper.EMPTY_OBJECT_ARRAY );
|
||||||
}
|
}
|
||||||
catch (InvocationTargetException ite) {
|
catch (InvocationTargetException ite) {
|
||||||
throw new PropertyAccessException(
|
throw new PropertyAccessException(
|
||||||
|
@ -24,14 +24,12 @@ public class NavigablePath implements DotIdentifierSequence {
|
|||||||
public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper";
|
public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper";
|
||||||
|
|
||||||
private final NavigablePath parent;
|
private final NavigablePath parent;
|
||||||
private final String localName;
|
|
||||||
private final String fullPath;
|
private final String fullPath;
|
||||||
|
|
||||||
private final int hashCode;
|
private final int hashCode;
|
||||||
|
|
||||||
public NavigablePath(NavigablePath parent, String navigableName) {
|
public NavigablePath(NavigablePath parent, String navigableName) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.localName = navigableName;
|
|
||||||
|
|
||||||
// the _identifierMapper is a "hidden property" on entities with composite keys.
|
// the _identifierMapper is a "hidden property" on entities with composite keys.
|
||||||
// concatenating it will prevent the path from correctly being used to look up
|
// concatenating it will prevent the path from correctly being used to look up
|
||||||
@ -54,31 +52,12 @@ public NavigablePath(NavigablePath parent, String navigableName) {
|
|||||||
this.hashCode = fullPath.hashCode();
|
this.hashCode = fullPath.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavigablePath(NavigablePath parent, String navigableName, String alias) {
|
|
||||||
assert parent != null;
|
|
||||||
|
|
||||||
this.parent = parent;
|
|
||||||
this.localName = navigableName;
|
|
||||||
|
|
||||||
final String prefix;
|
|
||||||
final String parentFullPath = parent.getFullPath();
|
|
||||||
|
|
||||||
prefix = StringHelper.isEmpty( parentFullPath )
|
|
||||||
? ""
|
|
||||||
: parentFullPath + '.';
|
|
||||||
|
|
||||||
this.fullPath = alias == null ? prefix : prefix + '(' + alias + ')';
|
|
||||||
|
|
||||||
this.hashCode = fullPath.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public NavigablePath(String localName) {
|
public NavigablePath(String localName) {
|
||||||
this( localName, null );
|
this( localName, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavigablePath(String rootName, String alias) {
|
public NavigablePath(String rootName, String alias) {
|
||||||
this.parent = null;
|
this.parent = null;
|
||||||
this.localName = rootName;
|
|
||||||
|
|
||||||
this.fullPath = alias == null ? rootName : rootName + '(' + alias + ')';
|
this.fullPath = alias == null ? rootName : rootName + '(' + alias + ')';
|
||||||
|
|
||||||
@ -102,7 +81,7 @@ public NavigablePath getParent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getLocalName() {
|
public String getLocalName() {
|
||||||
return localName;
|
return parent == null ? fullPath : StringHelper.unqualify( fullPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFullPath() {
|
public String getFullPath() {
|
||||||
|
@ -180,7 +180,7 @@ public SqmFromClause visitFromClause(SqmFromClause fromClause) {
|
|||||||
final SqmFromClause previousCurrent = currentFromClauseCopy;
|
final SqmFromClause previousCurrent = currentFromClauseCopy;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SqmFromClause copy = new SqmFromClause();
|
SqmFromClause copy = new SqmFromClause( fromClause.getNumberOfRoots() );
|
||||||
currentFromClauseCopy = copy;
|
currentFromClauseCopy = copy;
|
||||||
super.visitFromClause( fromClause );
|
super.visitFromClause( fromClause );
|
||||||
return copy;
|
return copy;
|
||||||
|
@ -804,7 +804,7 @@ public SqmFromClause visitFromClause(HqlParser.FromClauseContext parserFromClaus
|
|||||||
treatHandlerStack.push( new TreatHandlerFromClause() );
|
treatHandlerStack.push( new TreatHandlerFromClause() );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final SqmFromClause fromClause = new SqmFromClause();
|
final SqmFromClause fromClause = new SqmFromClause( parserFromClause.fromClauseSpace().size() );
|
||||||
for ( HqlParser.FromClauseSpaceContext parserSpace : parserFromClause.fromClauseSpace() ) {
|
for ( HqlParser.FromClauseSpaceContext parserSpace : parserFromClause.fromClauseSpace() ) {
|
||||||
final SqmRoot sqmPathRoot = visitFromClauseSpace( parserSpace );
|
final SqmRoot sqmPathRoot = visitFromClauseSpace( parserSpace );
|
||||||
fromClause.addRoot( sqmPathRoot );
|
fromClause.addRoot( sqmPathRoot );
|
||||||
|
@ -7,12 +7,15 @@
|
|||||||
package org.hibernate.query.internal;
|
package org.hibernate.query.internal;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.query.ParameterMetadata;
|
import org.hibernate.query.spi.HqlInterpretation;
|
||||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||||
|
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
||||||
import org.hibernate.query.spi.QueryInterpretationCache;
|
import org.hibernate.query.spi.QueryInterpretationCache;
|
||||||
import org.hibernate.query.spi.SelectQueryPlan;
|
import org.hibernate.query.spi.SelectQueryPlan;
|
||||||
import org.hibernate.query.sql.spi.ParameterInterpretation;
|
import org.hibernate.query.sql.spi.ParameterInterpretation;
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,14 +28,10 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation
|
|||||||
public static final QueryInterpretationCacheDisabledImpl INSTANCE = new QueryInterpretationCacheDisabledImpl();
|
public static final QueryInterpretationCacheDisabledImpl INSTANCE = new QueryInterpretationCacheDisabledImpl();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelectQueryPlan getSelectQueryPlan(Key key) {
|
public SelectQueryPlan resolveSelectQueryPlan(Key key, Supplier<SelectQueryPlan> creator) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cacheSelectQueryPlan(Key key, SelectQueryPlan plan) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NonSelectQueryPlan getNonSelectQueryPlan(Key key) {
|
public NonSelectQueryPlan getNonSelectQueryPlan(Key key) {
|
||||||
return null;
|
return null;
|
||||||
@ -43,8 +42,36 @@ public void cacheNonSelectQueryPlan(Key key, NonSelectQueryPlan plan) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmStatement resolveSqmStatement(String queryString, Function<String, SqmStatement<?>> creator) {
|
public HqlInterpretation resolveHqlInterpretation(String queryString, Function<String, SqmStatement<?>> creator) {
|
||||||
return creator.apply( queryString );
|
final SqmStatement<?> sqmStatement = creator.apply( queryString );
|
||||||
|
|
||||||
|
final DomainParameterXref domainParameterXref;
|
||||||
|
final ParameterMetadataImplementor parameterMetadata;
|
||||||
|
if ( sqmStatement.getSqmParameters().isEmpty() ) {
|
||||||
|
domainParameterXref = DomainParameterXref.empty();
|
||||||
|
parameterMetadata = ParameterMetadataImpl.EMPTY;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
domainParameterXref = DomainParameterXref.from( sqmStatement );
|
||||||
|
parameterMetadata = new ParameterMetadataImpl( domainParameterXref.getQueryParameters() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HqlInterpretation() {
|
||||||
|
@Override
|
||||||
|
public SqmStatement getSqmStatement() {
|
||||||
|
return sqmStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMetadataImplementor getParameterMetadata() {
|
||||||
|
return parameterMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainParameterXref getDomainParameterXref() {
|
||||||
|
return domainParameterXref;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -7,14 +7,19 @@
|
|||||||
package org.hibernate.query.internal;
|
package org.hibernate.query.internal;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.internal.util.collections.BoundedConcurrentHashMap;
|
import org.hibernate.internal.util.collections.BoundedConcurrentHashMap;
|
||||||
import org.hibernate.query.QueryLogger;
|
import org.hibernate.query.QueryLogger;
|
||||||
|
import org.hibernate.query.spi.HqlInterpretation;
|
||||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||||
|
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
||||||
import org.hibernate.query.spi.QueryInterpretationCache;
|
import org.hibernate.query.spi.QueryInterpretationCache;
|
||||||
import org.hibernate.query.spi.QueryPlan;
|
import org.hibernate.query.spi.QueryPlan;
|
||||||
import org.hibernate.query.spi.SelectQueryPlan;
|
import org.hibernate.query.spi.SelectQueryPlan;
|
||||||
|
import org.hibernate.query.spi.SimpleHqlInterpretationImpl;
|
||||||
import org.hibernate.query.sql.spi.ParameterInterpretation;
|
import org.hibernate.query.sql.spi.ParameterInterpretation;
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
@ -29,8 +34,12 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The default strong reference count.
|
* The default strong reference count.
|
||||||
|
*
|
||||||
|
* @deprecated No longer used
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static final int DEFAULT_PARAMETER_METADATA_MAX_COUNT = 128;
|
public static final int DEFAULT_PARAMETER_METADATA_MAX_COUNT = 128;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default soft reference count.
|
* The default soft reference count.
|
||||||
*/
|
*/
|
||||||
@ -41,27 +50,31 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
|
|||||||
*/
|
*/
|
||||||
private final BoundedConcurrentHashMap<Key, QueryPlan> queryPlanCache;
|
private final BoundedConcurrentHashMap<Key, QueryPlan> queryPlanCache;
|
||||||
|
|
||||||
private final BoundedConcurrentHashMap<String, SqmStatement<?>> sqmStatementCache;
|
private final BoundedConcurrentHashMap<String, HqlInterpretation> hqlInterpretationCache;
|
||||||
private final BoundedConcurrentHashMap<String, ParameterInterpretation> nativeQueryParamCache;
|
private final BoundedConcurrentHashMap<String, ParameterInterpretation> nativeQueryParamCache;
|
||||||
|
|
||||||
public QueryInterpretationCacheStandardImpl(int maxQueryPlanCount) {
|
public QueryInterpretationCacheStandardImpl(int maxQueryPlanCount) {
|
||||||
log.debugf( "Starting QueryPlanCache(%s)", maxQueryPlanCount );
|
log.debugf( "Starting QueryPlanCache(%s)", maxQueryPlanCount );
|
||||||
|
|
||||||
queryPlanCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
|
queryPlanCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
|
||||||
sqmStatementCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
|
hqlInterpretationCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
|
||||||
nativeQueryParamCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
|
nativeQueryParamCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelectQueryPlan getSelectQueryPlan(Key key) {
|
public SelectQueryPlan resolveSelectQueryPlan(
|
||||||
|
Key key,
|
||||||
|
Supplier<SelectQueryPlan> creator) {
|
||||||
log.tracef( "QueryPlan#getSelectQueryPlan(%s)", key );
|
log.tracef( "QueryPlan#getSelectQueryPlan(%s)", key );
|
||||||
return (SelectQueryPlan) queryPlanCache.get( key );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
final SelectQueryPlan cached = (SelectQueryPlan) queryPlanCache.get( key );
|
||||||
public void cacheSelectQueryPlan(Key key, SelectQueryPlan plan) {
|
if ( cached != null ) {
|
||||||
log.tracef( "QueryPlan#cacheSelectQueryPlan(%s)", key );
|
return cached;
|
||||||
queryPlanCache.putIfAbsent( key, plan );
|
}
|
||||||
|
|
||||||
|
final SelectQueryPlan plan = creator.get();
|
||||||
|
queryPlanCache.put( key, plan );
|
||||||
|
return plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,17 +89,37 @@ public void cacheNonSelectQueryPlan(Key key, NonSelectQueryPlan plan) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmStatement resolveSqmStatement(
|
public HqlInterpretation resolveHqlInterpretation(
|
||||||
String queryString,
|
String queryString,
|
||||||
Function<String, SqmStatement<?>> creator) {
|
Function<String, SqmStatement<?>> creator) {
|
||||||
log.tracef( "QueryPlan#resolveSqmStatement(%s)", queryString );
|
log.tracef( "QueryPlan#resolveHqlInterpretation( `%s` )", queryString );
|
||||||
return sqmStatementCache.computeIfAbsent(
|
|
||||||
queryString,
|
final HqlInterpretation cached = hqlInterpretationCache.get( queryString );
|
||||||
s -> {
|
if ( cached != null ) {
|
||||||
log.debugf( "Creating and caching SqmStatement - %s", queryString );
|
return cached;
|
||||||
return creator.apply( queryString );
|
}
|
||||||
}
|
|
||||||
);
|
log.debugf( "Creating and caching HqlInterpretation - %s", queryString );
|
||||||
|
|
||||||
|
final SqmStatement<?> sqmStatement = creator.apply( queryString );
|
||||||
|
final DomainParameterXref domainParameterXref;
|
||||||
|
final ParameterMetadataImplementor parameterMetadata;
|
||||||
|
|
||||||
|
if ( sqmStatement.getSqmParameters().isEmpty() ) {
|
||||||
|
domainParameterXref = DomainParameterXref.empty();
|
||||||
|
parameterMetadata = ParameterMetadataImpl.EMPTY;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
domainParameterXref = DomainParameterXref.from( sqmStatement );
|
||||||
|
parameterMetadata = new ParameterMetadataImpl( domainParameterXref.getQueryParameters() );
|
||||||
|
}
|
||||||
|
|
||||||
|
final HqlInterpretation interpretation = new SimpleHqlInterpretationImpl(
|
||||||
|
sqmStatement,
|
||||||
|
parameterMetadata,
|
||||||
|
domainParameterXref);
|
||||||
|
hqlInterpretationCache.put( queryString, interpretation );
|
||||||
|
return interpretation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package org.hibernate.query.spi;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface HqlInterpretation {
|
||||||
|
SqmStatement getSqmStatement();
|
||||||
|
|
||||||
|
ParameterMetadataImplementor getParameterMetadata();
|
||||||
|
|
||||||
|
DomainParameterXref getDomainParameterXref();
|
||||||
|
}
|
@ -16,6 +16,7 @@
|
|||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
|
||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
@ -64,6 +65,7 @@ public static QueryEngine from(
|
|||||||
private final SqmCriteriaNodeBuilder criteriaBuilder;
|
private final SqmCriteriaNodeBuilder criteriaBuilder;
|
||||||
private final HqlTranslator hqlTranslator;
|
private final HqlTranslator hqlTranslator;
|
||||||
private final SqmTranslatorFactory sqmTranslatorFactory;
|
private final SqmTranslatorFactory sqmTranslatorFactory;
|
||||||
|
private final NativeQueryInterpreter nativeQueryInterpreter;
|
||||||
private final QueryInterpretationCache interpretationCache;
|
private final QueryInterpretationCache interpretationCache;
|
||||||
private final SqmFunctionRegistry sqmFunctionRegistry;
|
private final SqmFunctionRegistry sqmFunctionRegistry;
|
||||||
|
|
||||||
@ -101,6 +103,8 @@ public QueryEngine(
|
|||||||
serviceRegistry
|
serviceRegistry
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.nativeQueryInterpreter = serviceRegistry.getService( NativeQueryInterpreter.class );
|
||||||
|
|
||||||
this.interpretationCache = buildInterpretationCache( properties );
|
this.interpretationCache = buildInterpretationCache( properties );
|
||||||
|
|
||||||
this.sqmFunctionRegistry = new SqmFunctionRegistry();
|
this.sqmFunctionRegistry = new SqmFunctionRegistry();
|
||||||
@ -163,20 +167,21 @@ private static QueryInterpretationCache buildInterpretationCache(Map properties)
|
|||||||
final boolean explicitUseCache = ConfigurationHelper.getBoolean(
|
final boolean explicitUseCache = ConfigurationHelper.getBoolean(
|
||||||
AvailableSettings.QUERY_PLAN_CACHE_ENABLED,
|
AvailableSettings.QUERY_PLAN_CACHE_ENABLED,
|
||||||
properties,
|
properties,
|
||||||
false
|
// enabled by default
|
||||||
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
final Integer explicitMaxPlanCount = ConfigurationHelper.getInteger(
|
final Integer explicitMaxPlanSize = ConfigurationHelper.getInteger(
|
||||||
AvailableSettings.QUERY_PLAN_CACHE_MAX_SIZE,
|
AvailableSettings.QUERY_PLAN_CACHE_MAX_SIZE,
|
||||||
properties
|
properties
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( explicitUseCache || ( explicitMaxPlanCount != null && explicitMaxPlanCount > 0 ) ) {
|
if ( explicitUseCache || ( explicitMaxPlanSize != null && explicitMaxPlanSize > 0 ) ) {
|
||||||
return new QueryInterpretationCacheStandardImpl(
|
final int size = explicitMaxPlanSize != null
|
||||||
explicitMaxPlanCount != null
|
? explicitMaxPlanSize
|
||||||
? explicitMaxPlanCount
|
: QueryInterpretationCacheStandardImpl.DEFAULT_QUERY_PLAN_MAX_COUNT;
|
||||||
: QueryInterpretationCacheStandardImpl.DEFAULT_QUERY_PLAN_MAX_COUNT
|
|
||||||
);
|
return new QueryInterpretationCacheStandardImpl( size );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// disabled
|
// disabled
|
||||||
@ -218,6 +223,10 @@ public SqmTranslatorFactory getSqmTranslatorFactory() {
|
|||||||
return sqmTranslatorFactory;
|
return sqmTranslatorFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NativeQueryInterpreter getNativeQueryInterpreter() {
|
||||||
|
return nativeQueryInterpreter;
|
||||||
|
}
|
||||||
|
|
||||||
public QueryInterpretationCache getInterpretationCache() {
|
public QueryInterpretationCache getInterpretationCache() {
|
||||||
return interpretationCache;
|
return interpretationCache;
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,14 @@
|
|||||||
package org.hibernate.query.spi;
|
package org.hibernate.query.spi;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.query.sql.spi.ParameterInterpretation;
|
import org.hibernate.query.sql.spi.ParameterInterpretation;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cache for QueryPlans used (and produced) by the translation
|
* Cache for various parts of translating or interpreting queries.
|
||||||
* and execution of a query.
|
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@ -23,13 +23,15 @@ public interface QueryInterpretationCache {
|
|||||||
interface Key {
|
interface Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectQueryPlan getSelectQueryPlan(Key key);
|
SelectQueryPlan resolveSelectQueryPlan(Key key, Supplier<SelectQueryPlan> creator);
|
||||||
void cacheSelectQueryPlan(Key key, SelectQueryPlan plan);
|
|
||||||
|
|
||||||
NonSelectQueryPlan getNonSelectQueryPlan(Key key);
|
NonSelectQueryPlan getNonSelectQueryPlan(Key key);
|
||||||
void cacheNonSelectQueryPlan(Key key, NonSelectQueryPlan plan);
|
void cacheNonSelectQueryPlan(Key key, NonSelectQueryPlan plan);
|
||||||
|
|
||||||
SqmStatement resolveSqmStatement(String queryString, Function<String, SqmStatement<?>> creator);
|
/**
|
||||||
|
* todo (6.0) : Doesn't holding these separate from the QueryPlans lead to extra, unnecessary memory use?
|
||||||
|
*/
|
||||||
|
HqlInterpretation resolveHqlInterpretation(String queryString, Function<String, SqmStatement<?>> creator);
|
||||||
|
|
||||||
ParameterInterpretation resolveNativeQueryParameters(String queryString, Function<String, ParameterInterpretation> creator);
|
ParameterInterpretation resolveNativeQueryParameters(String queryString, Function<String, ParameterInterpretation> creator);
|
||||||
|
|
||||||
@ -45,4 +47,5 @@ interface Key {
|
|||||||
* memory until they are replaced by others. It is not considered a memory leak as the cache is bounded.
|
* memory until they are replaced by others. It is not considered a memory leak as the cache is bounded.
|
||||||
*/
|
*/
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.spi;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SimpleHqlInterpretationImpl implements HqlInterpretation {
|
||||||
|
private final SqmStatement sqmStatement;
|
||||||
|
private final ParameterMetadataImplementor parameterMetadata;
|
||||||
|
private final DomainParameterXref domainParameterXref;
|
||||||
|
|
||||||
|
public SimpleHqlInterpretationImpl(
|
||||||
|
SqmStatement sqmStatement,
|
||||||
|
ParameterMetadataImplementor parameterMetadata,
|
||||||
|
DomainParameterXref domainParameterXref) {
|
||||||
|
this.sqmStatement = sqmStatement;
|
||||||
|
this.parameterMetadata = parameterMetadata;
|
||||||
|
this.domainParameterXref = domainParameterXref;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmStatement getSqmStatement() {
|
||||||
|
return sqmStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMetadataImplementor getParameterMetadata() {
|
||||||
|
return parameterMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainParameterXref getDomainParameterXref() {
|
||||||
|
return domainParameterXref;
|
||||||
|
}
|
||||||
|
}
|
@ -76,6 +76,7 @@
|
|||||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||||
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
||||||
import org.hibernate.query.sql.spi.NativeSelectQueryDefinition;
|
import org.hibernate.query.sql.spi.NativeSelectQueryDefinition;
|
||||||
|
import org.hibernate.query.sql.spi.NativeSelectQueryPlan;
|
||||||
import org.hibernate.query.sql.spi.NonSelectInterpretationsKey;
|
import org.hibernate.query.sql.spi.NonSelectInterpretationsKey;
|
||||||
import org.hibernate.query.sql.spi.ParameterInterpretation;
|
import org.hibernate.query.sql.spi.ParameterInterpretation;
|
||||||
import org.hibernate.query.sql.spi.SelectInterpretationsKey;
|
import org.hibernate.query.sql.spi.SelectInterpretationsKey;
|
||||||
@ -112,6 +113,7 @@ public class NativeQueryImpl<R>
|
|||||||
private boolean autoDiscoverTypes;
|
private boolean autoDiscoverTypes;
|
||||||
|
|
||||||
private Serializable collectionKey;
|
private Serializable collectionKey;
|
||||||
|
private NativeQueryInterpreter nativeQueryInterpreter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a NativeQueryImpl given a sql query defined in the mappings.
|
* Constructs a NativeQueryImpl given a sql query defined in the mappings.
|
||||||
@ -344,33 +346,31 @@ protected List<R> doList() {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private SelectQueryPlan<R> resolveSelectQueryPlan() {
|
private SelectQueryPlan<R> resolveSelectQueryPlan() {
|
||||||
final NativeQueryInterpreter interpreter = getSessionFactory().getServiceRegistry().getService( NativeQueryInterpreter.class );
|
|
||||||
|
|
||||||
SelectQueryPlan<R> queryPlan = null;
|
SelectQueryPlan<R> queryPlan = null;
|
||||||
|
|
||||||
|
|
||||||
final JdbcValuesMappingProducer resultSetMapping = getJdbcValuesMappingProducer();
|
final JdbcValuesMappingProducer resultSetMapping = getJdbcValuesMappingProducer();
|
||||||
final RowTransformer rowTransformer = resolveRowTransformer();
|
|
||||||
|
|
||||||
final QueryInterpretationCache.Key cacheKey = generateSelectInterpretationsKey( resultSetMapping );
|
final QueryInterpretationCache.Key cacheKey = generateSelectInterpretationsKey( resultSetMapping );
|
||||||
if ( cacheKey != null ) {
|
if ( cacheKey != null ) {
|
||||||
queryPlan = getSession().getFactory().getQueryEngine().getInterpretationCache().getSelectQueryPlan( cacheKey );
|
return getSession().getFactory().getQueryEngine().getInterpretationCache().resolveSelectQueryPlan(
|
||||||
}
|
cacheKey,
|
||||||
|
this::createQueryPlan
|
||||||
if ( queryPlan == null ) {
|
|
||||||
queryPlan = interpreter.createQueryPlan(
|
|
||||||
generateSelectQueryDefinition(),
|
|
||||||
getSessionFactory()
|
|
||||||
);
|
);
|
||||||
if ( cacheKey != null ) {
|
|
||||||
getSession().getFactory()
|
|
||||||
.getQueryEngine()
|
|
||||||
.getInterpretationCache()
|
|
||||||
.cacheSelectQueryPlan( cacheKey, queryPlan );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return createQueryPlan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return queryPlan;
|
private NativeSelectQueryPlan<R> createQueryPlan() {
|
||||||
|
final RowTransformer rowTransformer = resolveRowTransformer();
|
||||||
|
|
||||||
|
return getSessionFactory().getQueryEngine().getNativeQueryInterpreter().createQueryPlan(
|
||||||
|
generateSelectQueryDefinition(),
|
||||||
|
getSessionFactory()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JdbcValuesMappingProducer getJdbcValuesMappingProducer() {
|
private JdbcValuesMappingProducer getJdbcValuesMappingProducer() {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.query.QueryLogger;
|
import org.hibernate.query.QueryLogger;
|
||||||
import org.hibernate.query.internal.QueryParameterNamedImpl;
|
import org.hibernate.query.internal.QueryParameterNamedImpl;
|
||||||
import org.hibernate.query.internal.QueryParameterPositionalImpl;
|
import org.hibernate.query.internal.QueryParameterPositionalImpl;
|
||||||
@ -42,9 +43,6 @@ public class DomainParameterXref {
|
|||||||
* SQM statement
|
* SQM statement
|
||||||
*/
|
*/
|
||||||
public static DomainParameterXref from(SqmStatement<?> sqmStatement) {
|
public static DomainParameterXref from(SqmStatement<?> sqmStatement) {
|
||||||
final Map<QueryParameterImplementor<?>, List<SqmParameter>> sqmParamsByQueryParam = new IdentityHashMap<>();
|
|
||||||
final Map<SqmParameter, QueryParameterImplementor<?>> queryParamBySqmParam = new IdentityHashMap<>();
|
|
||||||
|
|
||||||
// `xrefMap` is used to help maintain the proper cardinality between an
|
// `xrefMap` is used to help maintain the proper cardinality between an
|
||||||
// SqmParameter and a QueryParameter. Multiple SqmParameter references
|
// SqmParameter and a QueryParameter. Multiple SqmParameter references
|
||||||
// can map to the same QueryParameter. Consider, e.g.,
|
// can map to the same QueryParameter. Consider, e.g.,
|
||||||
@ -90,6 +88,13 @@ else if ( o1 instanceof SqmJpaCriteriaParameterWrapper
|
|||||||
return empty();
|
return empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Map<QueryParameterImplementor<?>, List<SqmParameter>> sqmParamsByQueryParam = new IdentityHashMap<>();
|
||||||
|
|
||||||
|
final int sqmParamCount = parameterResolutions.getSqmParameters().size();
|
||||||
|
final Map<SqmParameter, QueryParameterImplementor<?>> queryParamBySqmParam = new IdentityHashMap<>(
|
||||||
|
CollectionHelper.determineProperSizing( sqmParamCount )
|
||||||
|
);
|
||||||
|
|
||||||
for ( SqmParameter<?> sqmParameter : parameterResolutions.getSqmParameters() ) {
|
for ( SqmParameter<?> sqmParameter : parameterResolutions.getSqmParameters() ) {
|
||||||
if ( sqmParameter instanceof JpaCriteriaParameter ) {
|
if ( sqmParameter instanceof JpaCriteriaParameter ) {
|
||||||
// see discussion on `SqmJpaCriteriaParameterWrapper#accept`
|
// see discussion on `SqmJpaCriteriaParameterWrapper#accept`
|
||||||
@ -181,6 +186,10 @@ public Set<QueryParameterImplementor<?>> getQueryParameters() {
|
|||||||
return sqmParamsByQueryParam.keySet();
|
return sqmParamsByQueryParam.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getQueryParameterCount() {
|
||||||
|
return sqmParamsByQueryParam.size();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the mapping of all QueryParameters to the List of its corresponding
|
* Get the mapping of all QueryParameters to the List of its corresponding
|
||||||
* SqmParameters
|
* SqmParameters
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
import org.hibernate.query.internal.QueryOptionsImpl;
|
import org.hibernate.query.internal.QueryOptionsImpl;
|
||||||
import org.hibernate.query.internal.QueryParameterBindingsImpl;
|
import org.hibernate.query.internal.QueryParameterBindingsImpl;
|
||||||
import org.hibernate.query.spi.AbstractQuery;
|
import org.hibernate.query.spi.AbstractQuery;
|
||||||
|
import org.hibernate.query.spi.HqlInterpretation;
|
||||||
import org.hibernate.query.spi.MutableQueryOptions;
|
import org.hibernate.query.spi.MutableQueryOptions;
|
||||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||||
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
||||||
@ -72,9 +73,9 @@ public class QuerySqmImpl<R>
|
|||||||
private final SqmStatement sqmStatement;
|
private final SqmStatement sqmStatement;
|
||||||
private final Class resultType;
|
private final Class resultType;
|
||||||
|
|
||||||
|
private final ParameterMetadataImplementor parameterMetadata;
|
||||||
private final DomainParameterXref domainParameterXref;
|
private final DomainParameterXref domainParameterXref;
|
||||||
|
|
||||||
private final ParameterMetadataImpl parameterMetadata;
|
|
||||||
private final QueryParameterBindingsImpl parameterBindings;
|
private final QueryParameterBindingsImpl parameterBindings;
|
||||||
|
|
||||||
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
|
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
|
||||||
@ -141,27 +142,57 @@ protected void applyOptions(NamedHqlQueryMemento memento) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form used for HQL queries
|
||||||
|
*/
|
||||||
public QuerySqmImpl(
|
public QuerySqmImpl(
|
||||||
String hqlString,
|
String hqlString,
|
||||||
|
HqlInterpretation hqlInterpretation,
|
||||||
|
Class resultType,
|
||||||
|
SharedSessionContractImplementor producer) {
|
||||||
|
super( producer );
|
||||||
|
|
||||||
|
this.hqlString = hqlString;
|
||||||
|
this.resultType = resultType;
|
||||||
|
|
||||||
|
this.sqmStatement = hqlInterpretation.getSqmStatement();
|
||||||
|
|
||||||
|
if ( resultType != null ) {
|
||||||
|
SqmUtil.verifyIsSelectStatement( sqmStatement );
|
||||||
|
//noinspection unchecked
|
||||||
|
checkQueryReturnType( (SqmSelectStatement<R>) sqmStatement, resultType, producer.getFactory() );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parameterMetadata = hqlInterpretation.getParameterMetadata();
|
||||||
|
this.domainParameterXref = hqlInterpretation.getDomainParameterXref();
|
||||||
|
|
||||||
|
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, producer.getFactory() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form used for criteria queries
|
||||||
|
*/
|
||||||
|
public QuerySqmImpl(
|
||||||
SqmStatement sqmStatement,
|
SqmStatement sqmStatement,
|
||||||
Class resultType,
|
Class resultType,
|
||||||
SharedSessionContractImplementor producer) {
|
SharedSessionContractImplementor producer) {
|
||||||
super( producer );
|
super( producer );
|
||||||
|
|
||||||
SqmUtil.verifyIsSelectStatement( sqmStatement );
|
|
||||||
checkQueryReturnType( (SqmSelectStatement<R>) sqmStatement, resultType, producer.getFactory() );
|
|
||||||
|
|
||||||
if ( resultType != null ) {
|
if ( resultType != null ) {
|
||||||
if ( sqmStatement instanceof SqmDmlStatement ) {
|
if ( sqmStatement instanceof SqmSelectStatement ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
checkQueryReturnType( (SqmSelectStatement<R>) sqmStatement, resultType, producer.getFactory() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert sqmStatement instanceof SqmDmlStatement;
|
||||||
throw new IllegalArgumentException( "Non-select queries cannot be typed" );
|
throw new IllegalArgumentException( "Non-select queries cannot be typed" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hqlString = hqlString;
|
this.hqlString = "<criteria>";
|
||||||
this.sqmStatement = sqmStatement;
|
this.sqmStatement = sqmStatement;
|
||||||
this.resultType = resultType;
|
this.resultType = resultType;
|
||||||
|
|
||||||
|
|
||||||
this.domainParameterXref = DomainParameterXref.from( sqmStatement );
|
this.domainParameterXref = DomainParameterXref.from( sqmStatement );
|
||||||
if ( ! domainParameterXref.hasParameters() ) {
|
if ( ! domainParameterXref.hasParameters() ) {
|
||||||
this.parameterMetadata = ParameterMetadataImpl.EMPTY;
|
this.parameterMetadata = ParameterMetadataImpl.EMPTY;
|
||||||
@ -391,27 +422,22 @@ private boolean requiresTxn(LockMode lockMode) {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private SelectQueryPlan<R> resolveSelectQueryPlan() {
|
private SelectQueryPlan<R> resolveSelectQueryPlan() {
|
||||||
// resolve (or make) the QueryPlan. This QueryPlan might be an
|
// resolve (or make) the QueryPlan. This QueryPlan might be an aggregation of multiple plans.
|
||||||
// aggregation of multiple plans. QueryPlans can be cached, except
|
//
|
||||||
// for in certain circumstances, the determination of which occurs in
|
// QueryPlans can be cached, except for in certain circumstances
|
||||||
// SqmInterpretationsKey#generateFrom - if SqmInterpretationsKey#generateFrom
|
// - the determination of these circumstances occurs in SqmInterpretationsKey#generateFrom.
|
||||||
// returns null the query is not cacheable
|
// If SqmInterpretationsKey#generateFrom returns null the query is not cacheable
|
||||||
|
|
||||||
SelectQueryPlan<R> queryPlan = null;
|
|
||||||
|
|
||||||
final QueryInterpretationCache.Key cacheKey = SqmInterpretationsKey.generateFrom( this );
|
final QueryInterpretationCache.Key cacheKey = SqmInterpretationsKey.generateFrom( this );
|
||||||
if ( cacheKey != null ) {
|
if ( cacheKey != null ) {
|
||||||
queryPlan = getSession().getFactory().getQueryEngine().getInterpretationCache().getSelectQueryPlan( cacheKey );
|
return getSession().getFactory().getQueryEngine().getInterpretationCache().resolveSelectQueryPlan(
|
||||||
|
cacheKey,
|
||||||
|
this::buildSelectQueryPlan
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if ( queryPlan == null ) {
|
return buildSelectQueryPlan();
|
||||||
queryPlan = buildSelectQueryPlan();
|
|
||||||
if ( cacheKey != null ) {
|
|
||||||
getSession().getFactory().getQueryEngine().getInterpretationCache().cacheSelectQueryPlan( cacheKey, queryPlan );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return queryPlan;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SelectQueryPlan<R> buildSelectQueryPlan() {
|
private SelectQueryPlan<R> buildSelectQueryPlan() {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.metamodel.mapping.Bindable;
|
import org.hibernate.metamodel.mapping.Bindable;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||||
@ -81,7 +82,10 @@ public static Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParam
|
|||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParameter>>> result = new IdentityHashMap<>();
|
final int queryParameterCount = domainParameterXref.getQueryParameterCount();
|
||||||
|
final Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParameter>>> result = new IdentityHashMap<>(
|
||||||
|
CollectionHelper.determineProperSizing( queryParameterCount )
|
||||||
|
);
|
||||||
|
|
||||||
for ( Map.Entry<QueryParameterImplementor<?>, List<SqmParameter>> entry :
|
for ( Map.Entry<QueryParameterImplementor<?>, List<SqmParameter>> entry :
|
||||||
domainParameterXref.getSqmParamByQueryParam().entrySet() ) {
|
domainParameterXref.getSqmParamByQueryParam().entrySet() ) {
|
||||||
|
@ -276,7 +276,7 @@ public SelectStatement visitSelectStatement(SqmSelectStatement statement) {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QuerySpec visitQuerySpec(SqmQuerySpec sqmQuerySpec) {
|
public QuerySpec visitQuerySpec(SqmQuerySpec sqmQuerySpec) {
|
||||||
final QuerySpec sqlQuerySpec = new QuerySpec( processingStateStack.isEmpty() );
|
final QuerySpec sqlQuerySpec = new QuerySpec( processingStateStack.isEmpty(), sqmQuerySpec.getFromClause().getNumberOfRoots() );
|
||||||
|
|
||||||
processingStateStack.push(
|
processingStateStack.push(
|
||||||
new SqlAstQuerySpecProcessingStateImpl(
|
new SqlAstQuerySpecProcessingStateImpl(
|
||||||
@ -737,12 +737,12 @@ protected MappingModelExpressable<?> determineValueMapping(SqmExpression<?> sqmE
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( sqmExpression instanceof SqmPath ) {
|
if ( sqmExpression instanceof SqmPath ) {
|
||||||
log.debugf( "Determining mapping-model type for SqmPath : " + sqmExpression );
|
log.debugf( "Determining mapping-model type for SqmPath : %s ", sqmExpression );
|
||||||
return SqmMappingModelHelper.resolveMappingModelExpressable( sqmExpression, this );
|
return SqmMappingModelHelper.resolveMappingModelExpressable( sqmExpression, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
log.debugf( "Determining mapping-model type for generalized SqmExpression : " + sqmExpression );
|
log.debugf( "Determining mapping-model type for generalized SqmExpression : %s", sqmExpression );
|
||||||
final SqmExpressable<?> nodeType = sqmExpression.getNodeType();
|
final SqmExpressable<?> nodeType = sqmExpression.getNodeType();
|
||||||
final MappingModelExpressable valueMapping = getCreationContext().getDomainModel().resolveMappingExpressable( nodeType );
|
final MappingModelExpressable valueMapping = getCreationContext().getDomainModel().resolveMappingExpressable( nodeType );
|
||||||
|
|
||||||
@ -763,7 +763,7 @@ protected MappingModelExpressable<?> determineValueMapping(SqmExpression<?> sqmE
|
|||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected MappingModelExpressable<?> determineValueMapping(SqmParameter<?> sqmParameter) {
|
protected MappingModelExpressable<?> determineValueMapping(SqmParameter<?> sqmParameter) {
|
||||||
log.debugf( "Determining mapping-model type for SqmParameter : " + sqmParameter );
|
log.debugf( "Determining mapping-model type for SqmParameter : %s", sqmParameter );
|
||||||
|
|
||||||
final QueryParameterImplementor<?> queryParameter = domainParameterXref.getQueryParameter( sqmParameter );
|
final QueryParameterImplementor<?> queryParameter = domainParameterXref.getQueryParameter( sqmParameter );
|
||||||
final QueryParameterBinding<?> binding = domainParameterBindings.getBinding( queryParameter );
|
final QueryParameterBinding<?> binding = domainParameterBindings.getBinding( queryParameter );
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
|
|
||||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
|
||||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.sql.internal;
|
package org.hibernate.query.sqm.sql.internal;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -21,6 +20,7 @@
|
|||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
import org.hibernate.graph.spi.AttributeNodeImplementor;
|
import org.hibernate.graph.spi.AttributeNodeImplementor;
|
||||||
import org.hibernate.graph.spi.GraphImplementor;
|
import org.hibernate.graph.spi.GraphImplementor;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
@ -71,7 +71,8 @@ public class StandardSqmSelectToSqlAstConverter
|
|||||||
private final LoadQueryInfluencers fetchInfluencers;
|
private final LoadQueryInfluencers fetchInfluencers;
|
||||||
private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector();
|
private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector();
|
||||||
|
|
||||||
private final List<DomainResult> domainResults = new ArrayList<>();
|
// prepare for 10 root selections to avoid list growth in most cases
|
||||||
|
private final List<DomainResult> domainResults = CollectionHelper.arrayList( 10 );
|
||||||
|
|
||||||
private GraphImplementor<?> currentJpaGraphNode;
|
private GraphImplementor<?> currentJpaGraphNode;
|
||||||
|
|
||||||
@ -154,29 +155,33 @@ private DomainResultProducer resolveDomainResultProducer(SqmSelection sqmSelecti
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Fetch> visitFetches(FetchParent fetchParent) {
|
public List<Fetch> visitFetches(FetchParent fetchParent) {
|
||||||
final List<Fetch> fetches = new ArrayList();
|
final List<Fetch> fetches = CollectionHelper.arrayList( fetchParent.getReferencedMappingType().getNumberOfAttributeMappings() );
|
||||||
|
|
||||||
final Consumer<Fetchable> fetchableConsumer = fetchable -> {
|
//noinspection Convert2Lambda
|
||||||
final Fetch biDirectionalFetch = circularFetchDetector.findBiDirectionalFetch(
|
final Consumer<Fetchable> fetchableConsumer = new Consumer<Fetchable>() {
|
||||||
fetchParent,
|
@Override
|
||||||
fetchable
|
public void accept(Fetchable fetchable) {
|
||||||
);
|
final Fetch biDirectionalFetch = circularFetchDetector.findBiDirectionalFetch(
|
||||||
|
fetchParent,
|
||||||
|
fetchable
|
||||||
|
);
|
||||||
|
|
||||||
if ( biDirectionalFetch != null ) {
|
if ( biDirectionalFetch != null ) {
|
||||||
fetches.add( biDirectionalFetch );
|
fetches.add( biDirectionalFetch );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fetchDepth++;
|
fetchDepth++;
|
||||||
final Fetch fetch = buildFetch( fetchParent, fetchable );
|
final Fetch fetch = buildFetch( fetchParent, fetchable );
|
||||||
|
|
||||||
if ( fetch != null ) {
|
if ( fetch != null ) {
|
||||||
fetches.add( fetch );
|
fetches.add( fetch );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
fetchDepth--;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
finally {
|
|
||||||
fetchDepth--;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -297,6 +302,7 @@ else if ( fetchDepth > maxDepth ) {
|
|||||||
try {
|
try {
|
||||||
return fetchable.generateFetch(
|
return fetchable.generateFetch(
|
||||||
fetchParent,
|
fetchParent,
|
||||||
|
fetchablePath,
|
||||||
fetchTiming,
|
fetchTiming,
|
||||||
joined,
|
joined,
|
||||||
lockMode,
|
lockMode,
|
||||||
|
@ -328,6 +328,6 @@ public SqmPath get(MapAttribute map) {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getSimpleName() + '(' + navigablePath.getFullPath() + ')';
|
return getClass().getSimpleName() + "(" + navigablePath.getFullPath() + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,12 +64,12 @@ public <X> X accept(SemanticQueryWalker<X> walker) {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedPath<T, S> treatAs(Class<S> treatJavaType) throws PathException {
|
public <S extends T> SqmTreatedPath<T, S> treatAs(Class<S> treatJavaType) throws PathException {
|
||||||
throw new UnsupportedOperationException();
|
throw new PathException( "Embeddable paths cannot be TREAT-ed" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedPath<T, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
|
public <S extends T> SqmTreatedPath<T, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
|
||||||
return null;
|
throw new PathException( "Embeddable paths cannot be TREAT-ed" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
|
|
||||||
@ -19,9 +20,14 @@
|
|||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class FromClause implements SqlAstNode {
|
public class FromClause implements SqlAstNode {
|
||||||
private final List<TableGroup> roots = new ArrayList<>();
|
private final List<TableGroup> roots;
|
||||||
|
|
||||||
public FromClause() {
|
public FromClause() {
|
||||||
|
roots = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FromClause(int expectedNumberOfRoots) {
|
||||||
|
roots = CollectionHelper.arrayList( expectedNumberOfRoots );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TableGroup> getRoots() {
|
public List<TableGroup> getRoots() {
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
public class QuerySpec implements SqlAstNode, PredicateContainer {
|
public class QuerySpec implements SqlAstNode, PredicateContainer {
|
||||||
private final boolean isRoot;
|
private final boolean isRoot;
|
||||||
|
|
||||||
private final FromClause fromClause = new FromClause();
|
private final FromClause fromClause;
|
||||||
private final SelectClause selectClause = new SelectClause();
|
private final SelectClause selectClause = new SelectClause();
|
||||||
|
|
||||||
private Predicate whereClauseRestrictions;
|
private Predicate whereClauseRestrictions;
|
||||||
@ -34,6 +34,12 @@ public class QuerySpec implements SqlAstNode, PredicateContainer {
|
|||||||
|
|
||||||
public QuerySpec(boolean isRoot) {
|
public QuerySpec(boolean isRoot) {
|
||||||
this.isRoot = isRoot;
|
this.isRoot = isRoot;
|
||||||
|
this.fromClause = new FromClause();
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuerySpec(boolean isRoot, int expectedNumberOfRoots) {
|
||||||
|
this.isRoot = isRoot;
|
||||||
|
this.fromClause = new FromClause( expectedNumberOfRoots );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,6 +99,7 @@ public FetchStrategy getMappedFetchStrategy() {
|
|||||||
@Override
|
@Override
|
||||||
public Fetch generateFetch(
|
public Fetch generateFetch(
|
||||||
FetchParent fetchParent,
|
FetchParent fetchParent,
|
||||||
|
NavigablePath fetchablePath,
|
||||||
FetchTiming fetchTiming,
|
FetchTiming fetchTiming,
|
||||||
boolean selected,
|
boolean selected,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
|
@ -39,13 +39,14 @@ public class BasicFetch<T> implements Fetch, BasicResultMappingNode<T> {
|
|||||||
public BasicFetch(
|
public BasicFetch(
|
||||||
int valuesArrayPosition,
|
int valuesArrayPosition,
|
||||||
FetchParent fetchParent,
|
FetchParent fetchParent,
|
||||||
|
NavigablePath fetchablePath,
|
||||||
BasicValuedModelPart valuedMapping,
|
BasicValuedModelPart valuedMapping,
|
||||||
boolean nullable,
|
boolean nullable,
|
||||||
BasicValueConverter valueConverter,
|
BasicValueConverter valueConverter,
|
||||||
FetchTiming fetchTiming,
|
FetchTiming fetchTiming,
|
||||||
DomainResultCreationState creationState) {
|
DomainResultCreationState creationState) {
|
||||||
this.nullable = nullable;
|
this.nullable = nullable;
|
||||||
this.navigablePath = fetchParent.getNavigablePath().append( valuedMapping.getFetchableName() );
|
this.navigablePath = fetchablePath;
|
||||||
|
|
||||||
this.fetchParent = fetchParent;
|
this.fetchParent = fetchParent;
|
||||||
this.valuedMapping = valuedMapping;
|
this.valuedMapping = valuedMapping;
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||||
@ -34,7 +36,7 @@ public abstract class AbstractEntityResultNode extends AbstractFetchParent imple
|
|||||||
|
|
||||||
private final EntityMappingType targetType;
|
private final EntityMappingType targetType;
|
||||||
|
|
||||||
private final List<DomainResult> attributeDomainResults = new ArrayList<>();
|
private final List<DomainResult> attributeDomainResults;
|
||||||
|
|
||||||
public AbstractEntityResultNode(
|
public AbstractEntityResultNode(
|
||||||
EntityValuedModelPart referencedModelPart,
|
EntityValuedModelPart referencedModelPart,
|
||||||
@ -92,18 +94,20 @@ public AbstractEntityResultNode(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// entityDescriptor.visitAttributeMappings(
|
|
||||||
// mapping -> attributeDomainResults.add(
|
|
||||||
// mapping.createDomainResult(
|
|
||||||
// navigablePath.append( mapping.getAttributeName() ),
|
|
||||||
// entityTableGroup,
|
|
||||||
// null,
|
|
||||||
// creationState
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
|
|
||||||
// todo (6.0) : handle other special navigables such as discriminator, row-id, tenant-id, etc
|
// todo (6.0) : handle other special navigables such as discriminator, row-id, tenant-id, etc
|
||||||
|
|
||||||
|
attributeDomainResults = CollectionHelper.arrayList( entityDescriptor.getNumberOfAttributeMappings() );
|
||||||
|
|
||||||
|
entityDescriptor.visitAttributeMappings(
|
||||||
|
mapping -> attributeDomainResults.add(
|
||||||
|
mapping.createDomainResult(
|
||||||
|
navigablePath.append( mapping.getAttributeName() ),
|
||||||
|
entityTableGroup,
|
||||||
|
null,
|
||||||
|
creationState
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,7 +37,7 @@ default SqlAliasBaseManager getSqlAliasBaseManager() {
|
|||||||
* BiFunction<FetchParent,Fetchable,LockMode> lockModeResolver)
|
* BiFunction<FetchParent,Fetchable,LockMode> lockModeResolver)
|
||||||
*
|
*
|
||||||
* [1] `selected` refers to the named parameter in
|
* [1] `selected` refers to the named parameter in
|
||||||
* {@link Fetchable#generateFetch(FetchParent, org.hibernate.engine.FetchTiming, boolean, LockMode, String, DomainResultCreationState)}.
|
* {@link Fetchable#generateFetch(FetchParent, org.hibernate.query.NavigablePath, org.hibernate.engine.FetchTiming, boolean, LockMode, String, DomainResultCreationState)}.
|
||||||
* For {@link org.hibernate.engine.FetchTiming#IMMEDIATE}, this boolean value indicates
|
* For {@link org.hibernate.engine.FetchTiming#IMMEDIATE}, this boolean value indicates
|
||||||
* whether the values for the generated assembler/initializers are or should be available in
|
* whether the values for the generated assembler/initializers are or should be available in
|
||||||
* the {@link JdbcValues} being processed. For {@link org.hibernate.engine.FetchTiming#DELAYED} this
|
* the {@link JdbcValues} being processed. For {@link org.hibernate.engine.FetchTiming#DELAYED} this
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
@ -26,6 +27,7 @@ public interface Fetchable extends ModelPart {
|
|||||||
|
|
||||||
Fetch generateFetch(
|
Fetch generateFetch(
|
||||||
FetchParent fetchParent,
|
FetchParent fetchParent,
|
||||||
|
NavigablePath fetchablePath,
|
||||||
FetchTiming fetchTiming,
|
FetchTiming fetchTiming,
|
||||||
boolean selected,
|
boolean selected,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
|
@ -11,15 +11,12 @@
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.boot.model.TypeContributor;
|
|
||||||
import org.hibernate.internal.util.SerializationHelper;
|
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
|
|
||||||
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.java.SerializableTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||||
import org.hibernate.type.descriptor.sql.VarbinaryTypeDescriptor;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
import org.hibernate.type.spi.TypeConfigurationAware;
|
import org.hibernate.type.spi.TypeConfigurationAware;
|
||||||
|
|
||||||
@ -74,19 +71,34 @@ private void performInjections(JavaTypeDescriptor descriptor) {
|
|||||||
// descriptor access
|
// descriptor access
|
||||||
|
|
||||||
public <T> JavaTypeDescriptor<T> getDescriptor(Class<T> javaType) {
|
public <T> JavaTypeDescriptor<T> getDescriptor(Class<T> javaType) {
|
||||||
return RegistryHelper.INSTANCE.resolveDescriptor(
|
return resolveDescriptor( javaType );
|
||||||
descriptorsByClass,
|
// return RegistryHelper.INSTANCE.resolveDescriptor(
|
||||||
javaType,
|
// descriptorsByClass,
|
||||||
() -> {
|
// javaType,
|
||||||
log.debugf(
|
// () -> {
|
||||||
"Could not find matching scoped JavaTypeDescriptor for requested Java class [%s]; " +
|
// log.debugf(
|
||||||
"falling back to static registry",
|
// "Could not find matching scoped JavaTypeDescriptor for requested Java class [%s]; " +
|
||||||
javaType.getName()
|
// "falling back to static registry",
|
||||||
);
|
// javaType.getName()
|
||||||
|
// );
|
||||||
return org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry.INSTANCE.getDescriptor( javaType );
|
//
|
||||||
}
|
// if ( Serializable.class.isAssignableFrom( javaType ) ) {
|
||||||
);
|
// return new SerializableTypeDescriptor( javaType );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ( !AttributeConverter.class.isAssignableFrom( javaType ) ) {
|
||||||
|
// log.debugf(
|
||||||
|
// "Could not find matching JavaTypeDescriptor for requested Java class [%s]; using fallback. " +
|
||||||
|
// "This means Hibernate does not know how to perform certain basic operations in relation to this Java type." +
|
||||||
|
// "",
|
||||||
|
// javaType.getName()
|
||||||
|
// );
|
||||||
|
// checkEqualsAndHashCode( javaType );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return new FallbackJavaTypeDescriptor<>( javaType );
|
||||||
|
// }
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDescriptor(JavaTypeDescriptor descriptor) {
|
public void addDescriptor(JavaTypeDescriptor descriptor) {
|
||||||
@ -103,15 +115,15 @@ public void addDescriptor(JavaTypeDescriptor descriptor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <J> JavaTypeDescriptor<J> resolveDescriptor(Class<J> javaType, Supplier<JavaTypeDescriptor<J>> creator) {
|
public <J> JavaTypeDescriptor<J> resolveDescriptor(Class<J> javaType, Supplier<JavaTypeDescriptor<J>> creator) {
|
||||||
//noinspection unchecked
|
final JavaTypeDescriptor cached = descriptorsByClass.get( javaType );
|
||||||
return descriptorsByClass.computeIfAbsent(
|
if ( cached != null ) {
|
||||||
javaType,
|
//noinspection unchecked
|
||||||
jt -> {
|
return cached;
|
||||||
final JavaTypeDescriptor<J> jtd = creator.get();
|
}
|
||||||
performInjections( jtd );
|
|
||||||
return jtd;
|
final JavaTypeDescriptor<J> created = creator.get();
|
||||||
}
|
descriptorsByClass.put( javaType, created );
|
||||||
);
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@ -126,7 +138,7 @@ public <J> JavaTypeDescriptor<J> resolveDescriptor(Class<J> javaType) {
|
|||||||
fallbackDescriptor = new EnumJavaTypeDescriptor( javaType );
|
fallbackDescriptor = new EnumJavaTypeDescriptor( javaType );
|
||||||
}
|
}
|
||||||
else if ( Serializable.class.isAssignableFrom( javaType ) ) {
|
else if ( Serializable.class.isAssignableFrom( javaType ) ) {
|
||||||
fallbackDescriptor = new OnTheFlySerializableJavaDescriptor( javaType );
|
fallbackDescriptor = new SerializableTypeDescriptor( javaType );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fallbackDescriptor = new JavaTypeDescriptorBasicAdaptor( javaType );
|
fallbackDescriptor = new JavaTypeDescriptorBasicAdaptor( javaType );
|
||||||
@ -146,7 +158,7 @@ public JavaTypeDescriptor<?> resolveDynamicDescriptor(String typeName) {
|
|||||||
return new DynamicJtd();
|
return new DynamicJtd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DynamicJtd implements JavaTypeDescriptor<Map> {
|
private static class DynamicJtd implements JavaTypeDescriptor<Map> {
|
||||||
@Override
|
@Override
|
||||||
public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) {
|
public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
@ -172,64 +184,4 @@ public Class<Map> getJavaTypeClass() {
|
|||||||
return Map.class;
|
return Map.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
private class OnTheFlySerializableJavaDescriptor<T extends Serializable> extends AbstractTypeDescriptor<T> {
|
|
||||||
private final SqlTypeDescriptor sqlTypeDescriptor;
|
|
||||||
|
|
||||||
public OnTheFlySerializableJavaDescriptor(Class<T> type) {
|
|
||||||
super( type );
|
|
||||||
|
|
||||||
// todo (6.0) : would be nice to expose for config by user
|
|
||||||
// todo (6.0) : ^^ might also be nice to allow them to plug in a "JavaTypeDescriptorResolver"
|
|
||||||
// - that allows them to hook into the #getDescriptor call either as the primary or as a fallback
|
|
||||||
|
|
||||||
|
|
||||||
log.debugf(
|
|
||||||
"Could not find matching JavaTypeDescriptor for requested Java class [%s]; using fallback via its Serializable interface. " +
|
|
||||||
"This means Hibernate does not know how to perform certain basic operations in relation to this Java type" +
|
|
||||||
"which can lead to those operations having a large performance impact. Consider registering these " +
|
|
||||||
"JavaTypeDescriptors with the %s during bootstrap, either directly or through a registered %s " +
|
|
||||||
"accessing the %s ",
|
|
||||||
getJavaType().getName(),
|
|
||||||
JavaTypeDescriptorRegistry.class.getName(),
|
|
||||||
TypeContributor.class.getName(),
|
|
||||||
TypeConfiguration.class.getName()
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
sqlTypeDescriptor = VarbinaryTypeDescriptor.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) {
|
|
||||||
return sqlTypeDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <X> X unwrap(T value, Class<X> type, WrapperOptions options) {
|
|
||||||
if ( type.equals( byte[].class ) ) {
|
|
||||||
throw new UnsupportedOperationException( "Cannot unwrap Serializable to format other than byte[]" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return (X) SerializationHelper.serialize( value );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <X> T wrap(X value, WrapperOptions options) {
|
|
||||||
if ( value == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( value.getClass().equals( byte[].class ) ) {
|
|
||||||
throw new UnsupportedOperationException( "Cannot unwrap Serializable to format other than byte[]" );
|
|
||||||
}
|
|
||||||
|
|
||||||
final byte[] bytes = (byte[]) value;
|
|
||||||
|
|
||||||
return (T) SerializationHelper.deserialize( bytes );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user