6 - SQM based on JPA type system

- further work on `org.hibernate.query` (especially `NamedQueryRepository` and friends)
- initial work on `org.hibernate.sql.exec`
- initial work on `org.hibernate.sql.results`
- SemanticPathPart handling
- NamedQueryMemento
- work on ProcedureCall
- continued work on `org.hibernate.sql.exec`
- continued work on `org.hibernate.sql.results`
- ported `hibernate-testing` JUnit 5 support
This commit is contained in:
Steve Ebersole 2019-06-05 14:33:21 -05:00 committed by Andrea Boriero
parent 46e27d7f46
commit 8d0ff71dfc
236 changed files with 10782 additions and 1154 deletions

View File

@ -0,0 +1,28 @@
/*
* 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;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.CLASS;
/**
* Annotation used to identify a package, class, interface or method
* as "internal", meaning that applications should expect no guarantees
* with regard to the binary stability from release to release.
*
* @author Steve Ebersole
*/
@Target({PACKAGE, TYPE, METHOD})
@Retention(CLASS)
public @interface Internal {
}

View File

@ -8,6 +8,7 @@ package org.hibernate.boot;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.IdentifierGeneratorDefinition;
@ -113,26 +114,31 @@ public interface Metadata extends Mapping {
/** /**
* Retrieve named query metadata by name. * Retrieve named query metadata by name.
* *
* @param name The query name
*
* @return The named query metadata, or {@code null}. * @return The named query metadata, or {@code null}.
*/ */
NamedHqlQueryDefinition getNamedHqlQueryMapping(String name); NamedHqlQueryDefinition getNamedHqlQueryMapping(String name);
java.util.Collection<NamedHqlQueryDefinition> getNamedHqlQueryMappings(); /**
* Visit all named HQL query definitions
*/
void visitNamedHqlQueryDefinitions(Consumer<NamedHqlQueryDefinition> definitionConsumer);
/** /**
* Retrieve named SQL query metadata. * Retrieve named SQL query metadata.
* *
* @param name The SQL query name.
*
* @return The named query metadata, or {@code null} * @return The named query metadata, or {@code null}
*/ */
NamedNativeQueryDefinition getNamedNativeQueryMapping(String name); NamedNativeQueryDefinition getNamedNativeQueryMapping(String name);
java.util.Collection<NamedNativeQueryDefinition> getNamedNativeQueryMappings(); /**
* Visit all named native query definitions
*/
void visitNamedNativeQueryDefinitions(Consumer<NamedNativeQueryDefinition> definitionConsumer);
java.util.Collection<NamedProcedureCallDefinition> getNamedProcedureCallMappings(); /**
* Visit all named callable query definitions
*/
void visitNamedProcedureCallDefinition(Consumer<NamedProcedureCallDefinition> definitionConsumer);
/** /**
* Retrieve the metadata for a named SQL result set mapping. * Retrieve the metadata for a named SQL result set mapping.
@ -143,13 +149,14 @@ public interface Metadata extends Mapping {
*/ */
NamedResultSetMappingDefinition getResultSetMapping(String name); NamedResultSetMappingDefinition getResultSetMapping(String name);
Map<String, NamedResultSetMappingDefinition> getResultSetMappingDefinitions(); /**
* Visit all named SQL result set mapping definitions
*/
void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer);
/** /**
* Retrieve a type definition by name. * Retrieve a type definition by name.
* *
* @param typeName The name of the type definition to retrieve.
*
* @return The named type definition, or {@code null} * @return The named type definition, or {@code null}
*/ */
TypeDefinition getTypeDefinition(String typeName); TypeDefinition getTypeDefinition(String typeName);

View File

@ -18,6 +18,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import javax.persistence.AttributeConverter; import javax.persistence.AttributeConverter;
import javax.persistence.Embeddable; import javax.persistence.Embeddable;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -79,12 +80,12 @@ import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.SQLFunction; import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
@ -228,7 +229,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
} }
@Override @Override
public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory) { public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) {
throw new UnsupportedOperationException( "#buildNamedQueryRepository should not be called on InFlightMetadataCollector" ); throw new UnsupportedOperationException( "#buildNamedQueryRepository should not be called on InFlightMetadataCollector" );
} }
@ -534,8 +535,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
} }
@Override @Override
public java.util.Collection<NamedHqlQueryDefinition> getNamedHqlQueryMappings() { public void visitNamedHqlQueryDefinitions(Consumer<NamedHqlQueryDefinition> definitionConsumer) {
return namedQueryMap.values(); namedQueryMap.values().forEach( definitionConsumer );
} }
@Override @Override
@ -580,8 +581,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
} }
@Override @Override
public java.util.Collection<NamedNativeQueryDefinition> getNamedNativeQueryMappings() { public void visitNamedNativeQueryDefinitions(Consumer<NamedNativeQueryDefinition> definitionConsumer) {
return namedNativeQueryMap.values(); namedNativeQueryMap.values().forEach( definitionConsumer );
} }
@Override @Override
@ -615,9 +616,10 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Named stored-procedure handling // Named stored-procedure handling
@Override @Override
public java.util.Collection<NamedProcedureCallDefinition> getNamedProcedureCallMappings() { public void visitNamedProcedureCallDefinition(Consumer<NamedProcedureCallDefinition> definitionConsumer) {
return namedProcedureCallMap.values(); namedProcedureCallMap.values().forEach( definitionConsumer );
} }
@Override @Override
@ -649,13 +651,13 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
// result-set mapping handling // result-set mapping handling
@Override @Override
public Map<String, NamedResultSetMappingDefinition> getResultSetMappingDefinitions() { public NamedResultSetMappingDefinition getResultSetMapping(String name) {
return sqlResultSetMappingMap; return sqlResultSetMappingMap.get( name );
} }
@Override @Override
public NamedResultSetMappingDefinition getResultSetMapping(String name) { public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer) {
return sqlResultSetMappingMap.get( name ); sqlResultSetMappingMap.values().forEach( definitionConsumer );
} }
@Override @Override

View File

@ -15,6 +15,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
@ -38,7 +39,6 @@ import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.mapping.FetchProfile; import org.hibernate.mapping.FetchProfile;
import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.MappedSuperclass;
@ -85,6 +85,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
private final Map<String, SQLFunction> sqlFunctionMap; private final Map<String, SQLFunction> sqlFunctionMap;
private final Database database; private final Database database;
@SuppressWarnings("WeakerAccess")
public MetadataImpl( public MetadataImpl(
UUID uuid, UUID uuid,
MetadataBuildingOptions metadataBuildingOptions, MetadataBuildingOptions metadataBuildingOptions,
@ -234,8 +235,8 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
} }
@Override @Override
public java.util.Collection<NamedHqlQueryDefinition> getNamedHqlQueryMappings() { public void visitNamedHqlQueryDefinitions(Consumer<NamedHqlQueryDefinition> definitionConsumer) {
return namedQueryMap.values(); namedQueryMap.values().forEach( definitionConsumer );
} }
@Override @Override
@ -244,13 +245,13 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
} }
@Override @Override
public java.util.Collection<NamedNativeQueryDefinition> getNamedNativeQueryMappings() { public void visitNamedNativeQueryDefinitions(Consumer<NamedNativeQueryDefinition> definitionConsumer) {
return namedNativeQueryMap.values(); namedNativeQueryMap.values().forEach( definitionConsumer );
} }
@Override @Override
public java.util.Collection<NamedProcedureCallDefinition> getNamedProcedureCallMappings() { public void visitNamedProcedureCallDefinition(Consumer<NamedProcedureCallDefinition> definitionConsumer) {
return namedProcedureCallMap.values(); namedProcedureCallMap.values().forEach( definitionConsumer );
} }
@Override @Override
@ -259,8 +260,8 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
} }
@Override @Override
public Map<String, NamedResultSetMappingDefinition> getResultSetMappingDefinitions() { public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer) {
return sqlResultSetMappingMap; sqlResultSetMappingMap.values().forEach( definitionConsumer );
} }
@Override @Override
@ -318,7 +319,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
} }
@Override @Override
public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory) { public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) {
return new NamedQueryRepositoryImpl( return new NamedQueryRepositoryImpl(
buildNamedHqlMementos( sessionFactory ), buildNamedHqlMementos( sessionFactory ),
buildNamedNativeMementos( sessionFactory ), buildNamedNativeMementos( sessionFactory ),
@ -335,7 +336,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
return map; return map;
} }
private Map<String, NamedNativeQueryMemento> buildNamedNativeMementos(SessionFactoryImpl sessionFactory) { private Map<String, NamedNativeQueryMemento> buildNamedNativeMementos(SessionFactoryImplementor sessionFactory) {
final HashMap<String, NamedNativeQueryMemento> map = new HashMap<>(); final HashMap<String, NamedNativeQueryMemento> map = new HashMap<>();
if ( namedNativeQueryMap != null ) { if ( namedNativeQueryMap != null ) {
namedNativeQueryMap.forEach( (key, value) -> map.put( key, value.resolve( sessionFactory ) ) ); namedNativeQueryMap.forEach( (key, value) -> map.put( key, value.resolve( sessionFactory ) ) );
@ -351,7 +352,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
return map; return map;
} }
private Map<String, NamedResultSetMappingMemento> buildResultSetMappingMementos(SessionFactoryImpl sessionFactory) { private Map<String, NamedResultSetMappingMemento> buildResultSetMappingMementos(SessionFactoryImplementor sessionFactory) {
final HashMap<String, NamedResultSetMappingMemento> map = new HashMap<>(); final HashMap<String, NamedResultSetMappingMemento> map = new HashMap<>();
if ( sqlResultSetMappingMap != null ) { if ( sqlResultSetMappingMap != null ) {
sqlResultSetMappingMap.forEach( (key, value) -> map.put( key, value.resolve( sessionFactory ) ) ); sqlResultSetMappingMap.forEach( (key, value) -> map.put( key, value.resolve( sessionFactory ) ) );

View File

@ -10,19 +10,17 @@ import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.boot.SessionFactoryBuilder; import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.internal.NamedProcedureCallDefinitionImpl;
import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition; import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Database;
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.dialect.function.SQLFunction; import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.mapping.FetchProfile; import org.hibernate.mapping.FetchProfile;
@ -118,13 +116,13 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
} }
@Override @Override
public NamedHqlQueryMementoImpl getNamedHqlQueryMapping(String name) { public NamedHqlQueryDefinition getNamedHqlQueryMapping(String name) {
return delegate.getNamedHqlQueryMapping( name ); return delegate.getNamedHqlQueryMapping( name );
} }
@Override @Override
public Collection<NamedHqlQueryMementoImpl> getNamedHqlQueryMappings() { public void visitNamedHqlQueryDefinitions(Consumer<NamedHqlQueryDefinition> definitionConsumer) {
return delegate.getNamedHqlQueryMappings(); delegate.visitNamedHqlQueryDefinitions( definitionConsumer );
} }
@Override @Override
@ -133,23 +131,23 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
} }
@Override @Override
public Collection<NamedNativeQueryDefinition> getNamedNativeQueryMappings() { public void visitNamedNativeQueryDefinitions(Consumer<NamedNativeQueryDefinition> definitionConsumer) {
return delegate.getNamedNativeQueryMappings(); delegate.visitNamedNativeQueryDefinitions( definitionConsumer );
} }
@Override @Override
public Collection<NamedProcedureCallDefinitionImpl> getNamedProcedureCallMappings() { public void visitNamedProcedureCallDefinition(Consumer<NamedProcedureCallDefinition> definitionConsumer) {
return delegate.getNamedProcedureCallMappings(); delegate.visitNamedProcedureCallDefinition( definitionConsumer );
} }
@Override @Override
public ResultSetMappingDescriptor getResultSetMapping(String name) { public NamedResultSetMappingDefinition getResultSetMapping(String name) {
return delegate.getResultSetMapping( name ); return delegate.getResultSetMapping( name );
} }
@Override @Override
public Map<String, ResultSetMappingDescriptor> getResultSetMappingDefinitions() { public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer) {
return delegate.getResultSetMappingDefinitions(); delegate.visitNamedResultSetMappingDefinition( definitionConsumer );
} }
@Override @Override
@ -224,11 +222,6 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
return delegate.getTypeResolver(); return delegate.getTypeResolver();
} }
@Override
public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory) {
return delegate.buildNamedQueryRepository( sessionFactory );
}
@Override @Override
public void validate() throws MappingException { public void validate() throws MappingException {
delegate.validate(); delegate.validate();

View File

@ -6,14 +6,12 @@
*/ */
package org.hibernate.boot.spi; package org.hibernate.boot.spi;
import java.util.Collection;
import java.util.Set; import java.util.Set;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.cache.cfg.internal.DomainDataRegionConfigImpl;
import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.Mapping;
import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.query.spi.NamedQueryRepository; import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -23,8 +21,6 @@ import org.hibernate.type.spi.TypeConfiguration;
/** /**
* The SPI-level Metadata contract. * The SPI-level Metadata contract.
* *
* @todo Should Mapping be implemented here, or on InFlightMetadataCollector instead?
*
* @author Steve Ebersole * @author Steve Ebersole
* *
* @since 5.0 * @since 5.0
@ -32,8 +28,6 @@ import org.hibernate.type.spi.TypeConfiguration;
public interface MetadataImplementor extends Metadata, Mapping { public interface MetadataImplementor extends Metadata, Mapping {
/** /**
* Access to the options used to build this Metadata * Access to the options used to build this Metadata
*
* @return
*/ */
MetadataBuildingOptions getMetadataBuildingOptions(); MetadataBuildingOptions getMetadataBuildingOptions();
@ -54,7 +48,7 @@ public interface MetadataImplementor extends Metadata, Mapping {
@Deprecated @Deprecated
TypeResolver getTypeResolver(); TypeResolver getTypeResolver();
NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory); NamedQueryRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory);
void validate() throws MappingException; void validate() throws MappingException;

View File

@ -33,6 +33,7 @@ import org.hibernate.loader.BatchFetchStyle;
import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode; import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.criteria.LiteralHandlingMode; import org.hibernate.query.criteria.LiteralHandlingMode;
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector; import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.stat.Statistics; import org.hibernate.stat.Statistics;
@ -315,5 +316,8 @@ public interface SessionFactoryOptions {
return false; return false;
} }
SqmFunctionRegistry getSqmFunctionRegistry();
boolean isOmitJoinOfSuperclassTablesEnabled(); boolean isOmitJoinOfSuperclassTablesEnabled();
} }

View File

@ -18,7 +18,7 @@ import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode; import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.internal.ParameterMetadataImpl; import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.resource.beans.container.spi.ExtendedBeanManager; import org.hibernate.resource.beans.container.spi.ExtendedBeanManager;
import org.hibernate.resource.transaction.spi.TransactionCoordinator; import org.hibernate.resource.transaction.spi.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder; import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
@ -1218,14 +1218,14 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
String QUERY_PLAN_CACHE_ENABLED = "hibernate.query.plan_cache_enabled"; String QUERY_PLAN_CACHE_ENABLED = "hibernate.query.plan_cache_enabled";
/** /**
* The maximum number of strong references maintained by {@link QueryPlanCache}. Default is 128. * The maximum number of strong references maintained by {@link QueryInterpretationCache}. Default is 128.
* @deprecated in favor of {@link #QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE} * @deprecated in favor of {@link #QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE}
*/ */
@Deprecated @Deprecated
String QUERY_PLAN_CACHE_MAX_STRONG_REFERENCES = "hibernate.query.plan_cache_max_strong_references"; String QUERY_PLAN_CACHE_MAX_STRONG_REFERENCES = "hibernate.query.plan_cache_max_strong_references";
/** /**
* The maximum number of soft references maintained by {@link QueryPlanCache}. Default is 2048. * The maximum number of soft references maintained by {@link QueryInterpretationCache}. Default is 2048.
* @deprecated in favor of {@link #QUERY_PLAN_CACHE_MAX_SIZE} * @deprecated in favor of {@link #QUERY_PLAN_CACHE_MAX_SIZE}
*/ */
@Deprecated @Deprecated
@ -1239,13 +1239,13 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
* <li>{@link org.hibernate.engine.query.spi.NativeSQLQueryPlan}</li> * <li>{@link org.hibernate.engine.query.spi.NativeSQLQueryPlan}</li>
* </ul> * </ul>
* *
* maintained by {@link QueryPlanCache}. Default is 2048. * maintained by {@link QueryInterpretationCache}. Default is 2048.
*/ */
String QUERY_PLAN_CACHE_MAX_SIZE = "hibernate.query.plan_cache_max_size"; String QUERY_PLAN_CACHE_MAX_SIZE = "hibernate.query.plan_cache_max_size";
/** /**
* The maximum number of {@link ParameterMetadataImpl} maintained * The maximum number of {@link ParameterMetadataImpl} maintained
* by {@link QueryPlanCache}. Default is 128. * by {@link QueryInterpretationCache}. Default is 128.
*/ */
String QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE = "hibernate.query.plan_parameter_metadata_max_size"; String QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE = "hibernate.query.plan_parameter_metadata_max_size";

View File

@ -97,6 +97,8 @@ import org.hibernate.mapping.Table;
import org.hibernate.persister.entity.Lockable; import org.hibernate.persister.entity.Lockable;
import org.hibernate.procedure.internal.StandardCallableStatementSupport; import org.hibernate.procedure.internal.StandardCallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ANSICaseFragment; import org.hibernate.sql.ANSICaseFragment;
import org.hibernate.sql.ANSIJoinFragment; import org.hibernate.sql.ANSIJoinFragment;
@ -261,6 +263,10 @@ public abstract class Dialect implements ConversionContext {
uniqueDelegate = new DefaultUniqueDelegate( this ); uniqueDelegate = new DefaultUniqueDelegate( this );
} }
public void initializeFunctionRegistry(QueryEngine queryEngine) {
}
/** /**
* Get an instance of the dialect specified by the current <tt>System</tt> properties. * Get an instance of the dialect specified by the current <tt>System</tt> properties.
* @deprecated this static method will be removed. * @deprecated this static method will be removed.
@ -2737,6 +2743,20 @@ public abstract class Dialect implements ConversionContext {
return useFollowOnLocking( null ); return useFollowOnLocking( null );
} }
/**
* Some dialects have trouble applying pessimistic locking depending upon what other query options are
* specified (paging, ordering, etc). This method allows these dialects to request that locking be applied
* by subsequent selects.
*
* @return {@code true} indicates that the dialect requests that locking be applied by subsequent select;
* {@code false} (the default) indicates that locking should be applied to the main SQL statement..
*
* @since 5.2
*/
public boolean useFollowOnLocking(String sql, QueryOptions queryOptions) {
return false;
}
/** /**
* Some dialects have trouble applying pessimistic locking depending upon what other query options are * Some dialects have trouble applying pessimistic locking depending upon what other query options are
* specified (paging, ordering, etc). This method allows these dialects to request that locking be applied * specified (paging, ordering, etc). This method allows these dialects to request that locking be applied

View File

@ -17,12 +17,10 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceUnitUtil; import javax.persistence.PersistenceUnitUtil;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.SynchronizationType; import javax.persistence.SynchronizationType;
import javax.persistence.criteria.CriteriaBuilder;
import org.hibernate.CustomEntityDirtinessStrategy; import org.hibernate.CustomEntityDirtinessStrategy;
import org.hibernate.EntityNameResolver; import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
@ -36,27 +34,28 @@ import org.hibernate.cfg.Settings;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.SQLFunctionRegistry; import org.hibernate.dialect.function.SQLFunctionRegistry;
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.spi.QueryPlanCache;
import org.hibernate.exception.spi.SQLExceptionConverter; import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metadata.CollectionMetadata; import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.spi.NamedQueryRepository; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver; import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
/** /**
* Base delegating implementation of the SessionFactory and SessionFactoryImplementor * Base delegating implementation of the SessionFactory and SessionFactoryImplementor
@ -208,6 +207,11 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getTypeResolver(); return delegate.getTypeResolver();
} }
@Override
public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
return delegate.getIdentifierGenerator( rootEntityName );
}
@Override @Override
public Map<String, Object> getProperties() { public Map<String, Object> getProperties() {
return delegate.getProperties(); return delegate.getProperties();
@ -243,26 +247,6 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getDialect(); return delegate.getDialect();
} }
@Override
public Interceptor getInterceptor() {
return delegate.getInterceptor();
}
@Override
public QueryPlanCache getQueryPlanCache() {
return delegate.getQueryPlanCache();
}
@Override
public Type[] getReturnTypes(String queryString) throws HibernateException {
return delegate.getReturnTypes( queryString );
}
@Override
public String[] getReturnAliases(String queryString) throws HibernateException {
return delegate.getReturnAliases( queryString );
}
@Override @Override
public String[] getImplementors(String className) throws MappingException { public String[] getImplementors(String className) throws MappingException {
return delegate.getImplementors( className ); return delegate.getImplementors( className );
@ -283,36 +267,6 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getStatistics(); return delegate.getStatistics();
} }
@Override
public NamedHqlQueryMementoImpl getNamedQuery(String queryName) {
return delegate.getNamedQuery( queryName );
}
@Override
public void registerNamedQueryDefinition(String name, NamedHqlQueryMementoImpl memento) {
delegate.registerNamedQueryDefinition( name, memento );
}
@Override
public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) {
return delegate.getNamedSQLQuery( queryName );
}
@Override
public void registerNamedSQLQueryDefinition(String name, NamedSQLQueryDefinition definition) {
delegate.registerNamedSQLQueryDefinition( name, definition );
}
@Override
public ResultSetMappingDescriptor getResultSetMapping(String name) {
return delegate.getResultSetMapping( name );
}
@Override
public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
return delegate.getIdentifierGenerator( rootEntityName );
}
@Override @Override
public SQLExceptionConverter getSQLExceptionConverter() { public SQLExceptionConverter getSQLExceptionConverter() {
return delegate.getSQLExceptionConverter(); return delegate.getSQLExceptionConverter();
@ -353,11 +307,21 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getFetchProfile( name ); return delegate.getFetchProfile( name );
} }
@Override
public JpaMetamodel getJpaMetamodel() {
return delegate.getJpaMetamodel();
}
@Override @Override
public ServiceRegistryImplementor getServiceRegistry() { public ServiceRegistryImplementor getServiceRegistry() {
return delegate.getServiceRegistry(); return delegate.getServiceRegistry();
} }
@Override
public Integer getMaximumFetchDepth() {
return delegate.getMaximumFetchDepth();
}
@Override @Override
public void addObserver(SessionFactoryObserver observer) { public void addObserver(SessionFactoryObserver observer) {
delegate.addObserver( observer ); delegate.addObserver( observer );
@ -373,11 +337,6 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getCurrentTenantIdentifierResolver(); return delegate.getCurrentTenantIdentifierResolver();
} }
@Override
public NamedQueryRepository getNamedQueryRepository() {
return delegate.getNamedQueryRepository();
}
@Override @Override
public Iterable<EntityNameResolver> iterateEntityNameResolvers() { public Iterable<EntityNameResolver> iterateEntityNameResolvers() {
return delegate.iterateEntityNameResolvers(); return delegate.iterateEntityNameResolvers();
@ -428,6 +387,16 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getName(); return delegate.getName();
} }
@Override
public TypeConfiguration getTypeConfiguration() {
return delegate.getTypeConfiguration();
}
@Override
public QueryEngine getQueryEngine() {
return delegate.getQueryEngine();
}
@Override @Override
public Reference getReference() throws NamingException { public Reference getReference() throws NamingException {
return delegate.getReference(); return delegate.getReference();
@ -459,7 +428,7 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
} }
@Override @Override
public CriteriaBuilder getCriteriaBuilder() { public NodeBuilder getCriteriaBuilder() {
return delegate.getCriteriaBuilder(); return delegate.getCriteriaBuilder();
} }
@ -474,12 +443,12 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
} }
@Override @Override
public Type resolveParameterBindType(Object bindValue) { public AllowableParameterType<?> resolveParameterBindType(Object bindValue) {
return delegate.resolveParameterBindType( bindValue ); return delegate.resolveParameterBindType( bindValue );
} }
@Override @Override
public Type resolveParameterBindType(Class clazz) { public AllowableParameterType<?> resolveParameterBindType(Class<?> clazz) {
return delegate.resolveParameterBindType( clazz ); return delegate.resolveParameterBindType( clazz );
} }
} }

View File

@ -15,13 +15,11 @@ import javax.persistence.EntityGraph;
import org.hibernate.CustomEntityDirtinessStrategy; import org.hibernate.CustomEntityDirtinessStrategy;
import org.hibernate.EntityNameResolver; import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.Metamodel; import org.hibernate.Metamodel;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver; import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.spi.CacheImplementor; import org.hibernate.cache.spi.CacheImplementor;
import org.hibernate.cfg.Settings; import org.hibernate.cfg.Settings;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
@ -38,18 +36,12 @@ import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.query.spi.NamedResultSetMappingMemento;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryParameterBindingTypeResolver; import org.hibernate.query.spi.QueryParameterBindingTypeResolver;
import org.hibernate.query.spi.QueryPlanCache;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.produce.spi.SqmCreationContext; import org.hibernate.query.sqm.produce.spi.SqmCreationContext;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.sql.ast.produce.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver; import org.hibernate.type.TypeResolver;
@ -117,38 +109,6 @@ public interface SessionFactoryImplementor
*/ */
ServiceRegistryImplementor getServiceRegistry(); ServiceRegistryImplementor getServiceRegistry();
/**
* Get the factory scoped interceptor for this factory.
*
* @return The factory scope interceptor, or null if none.
*
* @deprecated (since 5.2) if access to the SessionFactory-scoped Interceptor is needed, use
* {@link SessionFactoryOptions#getInterceptor()} instead. However, generally speaking this access
* is not needed.
*/
@Deprecated
Interceptor getInterceptor();
/**
* Access to the cachres of HQL/JPQL and native query plans.
*
* @return The query plan cache
*
* @deprecated (since 5.2) it will be replaced with the new QueryEngine concept introduced in 6.0
*/
@Deprecated
QueryPlanCache getQueryPlanCache();
/**
* Provides access to the named query repository
*
* @return The repository for named query definitions
*
* @deprecated (since 5.2) it will be replaced with the new QueryEngine concept introduced in 6.0
*/
@Deprecated
NamedQueryRepository getNamedQueryRepository();
/** /**
* Retrieve fetch profile by name. * Retrieve fetch profile by name.
* *
@ -212,28 +172,6 @@ public interface SessionFactoryImplementor
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Deprecations // Deprecations
/**
* Get the return types of a query
*
* @deprecated No replacement.
*/
@Deprecated
default Type[] getReturnTypes(String queryString) {
throw new UnsupportedOperationException( "Concept of query return org.hibernate.type.Types is no longer supported" );
}
/**
* Get the return aliases of a query
*
* @deprecated No replacement.
*/
@Deprecated
default String[] getReturnAliases(String queryString) {
throw new UnsupportedOperationException( "Access to of query return aliases via Sessionfactory is no longer supported" );
}
/** /**
* @deprecated (since 5.2) Just use {@link #getStatistics} (with covariant return here as {@link StatisticsImplementor}). * @deprecated (since 5.2) Just use {@link #getStatistics} (with covariant return here as {@link StatisticsImplementor}).
*/ */
@ -242,51 +180,6 @@ public interface SessionFactoryImplementor
return getStatistics(); return getStatistics();
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NamedQueryRepository
/**
* @deprecated (since 5.2) Use {@link NamedQueryRepository#getHqlQueryMemento} instead.
*/
@Deprecated
default NamedHqlQueryMemento getNamedQuery(String queryName) {
return getNamedQueryRepository().getHqlQueryMemento( queryName );
}
/**
* @deprecated (since 5.2) Use {@link NamedQueryRepository#registerHqlQueryMemento} instead.
*/
@Deprecated
default void registerNamedQueryDefinition(String name, NamedHqlQueryMementoImpl memento) {
getNamedQueryRepository().registerHqlQueryMemento( name, memento );
}
/**
* @deprecated (since 5.2) Use {@link NamedQueryRepository#getNativeQueryMemento} instead.
*/
@Deprecated
default NamedNativeQueryMemento getNamedSQLQuery(String queryName) {
return getNamedQueryRepository().getNativeQueryMemento( queryName );
}
/**
* @deprecated (since 5.2) Use {@link NamedQueryRepository#registerNativeQueryMemento} instead.
*/
@Deprecated
default void registerNamedSQLQueryDefinition(String name, NamedNativeQueryMemento memento) {
getNamedQueryRepository().registerNativeQueryMemento( name, memento );
}
/**
* @deprecated (since 5.2) Use {@link NamedQueryRepository#getResultSetMappingMemento} instead.
*/
@Deprecated
default NamedResultSetMappingMemento getResultSetMapping(String name) {
return getNamedQueryRepository().getResultSetMappingMemento( name );
}
/** /**
* Get the JdbcServices. * Get the JdbcServices.
* *

View File

@ -606,11 +606,11 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
} }
protected HQLQueryPlan getQueryPlan(String query, boolean shallow) throws HibernateException { protected HQLQueryPlan getQueryPlan(String query, boolean shallow) throws HibernateException {
return getFactory().getQueryPlanCache().getHQLQueryPlan( query, shallow, getLoadQueryInfluencers().getEnabledFilters() ); return getFactory().getQueryInterpretationCache().getHQLQueryPlan( query, shallow, getLoadQueryInfluencers().getEnabledFilters() );
} }
protected NativeSQLQueryPlan getNativeQueryPlan(NativeSQLQuerySpecification spec) throws HibernateException { protected NativeSQLQueryPlan getNativeQueryPlan(NativeSQLQuerySpecification spec) throws HibernateException {
return getFactory().getQueryPlanCache().getNativeSQLQueryPlan( spec ); return getFactory().getQueryInterpretationCache().getNativeSQLQueryPlan( spec );
} }
@Override @Override
@ -640,7 +640,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
} }
private NativeQueryImplementor createNativeQuery(NamedNativeQueryMemento queryDefinition, boolean isOrdinalParameterZeroBased) { private NativeQueryImplementor createNativeQuery(NamedNativeQueryMemento queryDefinition, boolean isOrdinalParameterZeroBased) {
final ParameterMetadata parameterMetadata = factory.getQueryPlanCache().getSQLParameterMetadata( final ParameterMetadata parameterMetadata = factory.getQueryInterpretationCache().getSQLParameterMetadata(
queryDefinition.getQueryString(), queryDefinition.getQueryString(),
isOrdinalParameterZeroBased isOrdinalParameterZeroBased
); );
@ -733,7 +733,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
@SuppressWarnings({"unchecked", "WeakerAccess", "StatementWithEmptyBody"}) @SuppressWarnings({"unchecked", "WeakerAccess", "StatementWithEmptyBody"})
protected void resultClassChecking(Class resultClass, Query hqlQuery) { protected void resultClassChecking(Class resultClass, Query hqlQuery) {
// make sure the query is a select -> HHH-7192 // make sure the query is a select -> HHH-7192
final HQLQueryPlan queryPlan = getFactory().getQueryPlanCache().getHQLQueryPlan( final HQLQueryPlan queryPlan = getFactory().getQueryInterpretationCache().getHQLQueryPlan(
hqlQuery.getQueryString(), hqlQuery.getQueryString(),
false, false,
getLoadQueryInfluencers().getEnabledFilters() getLoadQueryInfluencers().getEnabledFilters()
@ -829,7 +829,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
final NativeQueryImpl query = new NativeQueryImpl( final NativeQueryImpl query = new NativeQueryImpl(
queryDefinition, queryDefinition,
this, this,
factory.getQueryPlanCache().getSQLParameterMetadata( queryDefinition.getQueryString(), false ) factory.getQueryInterpretationCache().getSQLParameterMetadata( queryDefinition.getQueryString(), false )
); );
if ( Tuple.class.equals( resultType ) ) { if ( Tuple.class.equals( resultType ) ) {
query.setResultTransformer( new NativeQueryTupleTransformer() ); query.setResultTransformer( new NativeQueryTupleTransformer() );
@ -982,7 +982,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
queryString, queryString,
false, false,
this, this,
getFactory().getQueryPlanCache().getSQLParameterMetadata( queryString, isOrdinalParameterZeroBased ) getFactory().getQueryInterpretationCache().getSQLParameterMetadata( queryString, isOrdinalParameterZeroBased )
); );
query.setComment( "dynamic native SQL query" ); query.setComment( "dynamic native SQL query" );
return query; return query;

View File

@ -73,7 +73,6 @@ import org.hibernate.engine.jndi.spi.JndiService;
import org.hibernate.engine.profile.Association; import org.hibernate.engine.profile.Association;
import org.hibernate.engine.profile.Fetch; import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.query.spi.ReturnMetadata;
import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.SessionBuilderImplementor; import org.hibernate.engine.spi.SessionBuilderImplementor;
import org.hibernate.engine.spi.SessionEventListenerManager; import org.hibernate.engine.spi.SessionEventListenerManager;
@ -97,15 +96,18 @@ import org.hibernate.jpa.internal.PersistenceUnitUtilImpl;
import org.hibernate.mapping.RootClass; import org.hibernate.mapping.RootClass;
import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metadata.CollectionMetadata; import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Loadable;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.spi.ProcedureCallImplementor;
import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.proxy.HibernateProxyHelper; import org.hibernate.proxy.HibernateProxyHelper;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl; import org.hibernate.query.hql.spi.HqlQueryImplementor;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.sql.spi.NativeQueryImplementor;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder; import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
import org.hibernate.query.NativeQuery; import org.hibernate.query.NativeQuery;
@ -125,9 +127,9 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tool.schema.spi.DelayedDropAction; import org.hibernate.tool.schema.spi.DelayedDropAction;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator; import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
import org.hibernate.type.SerializableType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver; import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -180,8 +182,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
private final transient NodeBuilder criteriaBuilder; private final transient NodeBuilder criteriaBuilder;
private final PersistenceUnitUtil jpaPersistenceUnitUtil; private final PersistenceUnitUtil jpaPersistenceUnitUtil;
private final transient CacheImplementor cacheAccess; private final transient CacheImplementor cacheAccess;
private final transient NamedQueryRepository namedQueryRepository; private final transient QueryEngine queryEngine;
private final transient QueryPlanCache queryPlanCache;
private final transient CurrentSessionContext currentSessionContext; private final transient CurrentSessionContext currentSessionContext;
@ -213,6 +214,8 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
prepareEventListeners( metadata ); prepareEventListeners( metadata );
this.queryEngine = QueryEngine.from( this, metadata );
final CfgXmlAccessService cfgXmlAccessService = serviceRegistry.getService( CfgXmlAccessService.class ); final CfgXmlAccessService cfgXmlAccessService = serviceRegistry.getService( CfgXmlAccessService.class );
String sfName = settings.getSessionFactoryName(); String sfName = settings.getSessionFactoryName();
@ -244,7 +247,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
this.sqlFunctionRegistry = new SQLFunctionRegistry( jdbcServices.getJdbcEnvironment().getDialect(), options.getCustomSqlFunctionMap() ); this.sqlFunctionRegistry = new SQLFunctionRegistry( jdbcServices.getJdbcEnvironment().getDialect(), options.getCustomSqlFunctionMap() );
this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class ); this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class );
this.criteriaBuilder = new SqmCriteriaNodeBuilder.create( this ); this.criteriaBuilder = SqmCriteriaNodeBuilder.create( this );
this.jpaPersistenceUnitUtil = new PersistenceUnitUtilImpl( this ); this.jpaPersistenceUnitUtil = new PersistenceUnitUtilImpl( this );
for ( SessionFactoryObserver sessionFactoryObserver : options.getSessionFactoryObservers() ) { for ( SessionFactoryObserver sessionFactoryObserver : options.getSessionFactoryObservers() ) {
@ -259,8 +262,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
LOG.debugf( "Session factory constructed with filter configurations : %s", filters ); LOG.debugf( "Session factory constructed with filter configurations : %s", filters );
LOG.debugf( "Instantiating session factory with properties: %s", properties ); LOG.debugf( "Instantiating session factory with properties: %s", properties );
this.queryPlanCache = new QueryPlanCache( this );
class IntegratorObserver implements SessionFactoryObserver { class IntegratorObserver implements SessionFactoryObserver {
private ArrayList<Integrator> integrators = new ArrayList<>(); private ArrayList<Integrator> integrators = new ArrayList<>();
@ -301,9 +302,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
this.metamodel = (MetamodelImplementor) metadata.getTypeConfiguration().scope( this ) this.metamodel = (MetamodelImplementor) metadata.getTypeConfiguration().scope( this )
.create( metadata, determineJpaMetaModelPopulationSetting( properties ) ); .create( metadata, determineJpaMetaModelPopulationSetting( properties ) );
//Named Queries:
this.namedQueryRepository = metadata.buildNamedQueryRepository( this );
settings.getMultiTableBulkIdStrategy().prepare( settings.getMultiTableBulkIdStrategy().prepare(
jdbcServices, jdbcServices,
buildLocalConnectionAccess(), buildLocalConnectionAccess(),
@ -320,26 +318,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
currentSessionContext = buildCurrentSessionContext(); currentSessionContext = buildCurrentSessionContext();
//checking for named queries
if ( settings.isNamedQueryStartupCheckingEnabled() ) {
final Map<String, HibernateException> errors = checkNamedQueries();
if ( !errors.isEmpty() ) {
StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " );
String separator = System.lineSeparator();
for ( Map.Entry<String, HibernateException> entry : errors.entrySet() ) {
LOG.namedQueryError( entry.getKey(), entry.getValue() );
failingQueries
.append( separator)
.append( entry.getKey() )
.append( " failed because of: " )
.append( entry.getValue() );
}
throw new HibernateException( failingQueries.toString() );
}
}
// this needs to happen after persisters are all ready to go... // this needs to happen after persisters are all ready to go...
this.fetchProfiles = new HashMap<>(); this.fetchProfiles = new HashMap<>();
for ( org.hibernate.mapping.FetchProfile mappingProfile : metadata.getFetchProfiles() ) { for ( org.hibernate.mapping.FetchProfile mappingProfile : metadata.getFetchProfiles() ) {
@ -408,7 +386,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
eventListenerRegistry.prepare( metadata ); eventListenerRegistry.prepare( metadata );
for ( Map.Entry entry : ( (Map<?, ?>) cfgService.getSettings() ).entrySet() ) { for ( Map.Entry entry : ( (Map<?, ?>) cfgService.getSettings() ).entrySet() ) {
if ( !String.class.isInstance( entry.getKey() ) ) { if ( !(entry.getKey() instanceof String) ) {
continue; continue;
} }
final String propertyName = (String) entry.getKey(); final String propertyName = (String) entry.getKey();
@ -421,6 +399,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
final EventType eventType = EventType.resolveEventTypeByName( eventTypeName ); final EventType eventType = EventType.resolveEventTypeByName( eventTypeName );
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType ); final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
for ( String listenerImpl : LISTENER_SEPARATION_PATTERN.split( ( (String) entry.getValue() ) ) ) { for ( String listenerImpl : LISTENER_SEPARATION_PATTERN.split( ( (String) entry.getValue() ) ) ) {
//noinspection unchecked
eventListenerGroup.appendListener( instantiate( listenerImpl, classLoaderService ) ); eventListenerGroup.appendListener( instantiate( listenerImpl, classLoaderService ) );
} }
} }
@ -534,6 +513,16 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
return name; return name;
} }
@Override
public TypeConfiguration getTypeConfiguration() {
return getMetamodel().getTypeConfiguration();
}
@Override
public QueryEngine getQueryEngine() {
return null;
}
@Override @Override
public JdbcServices getJdbcServices() { public JdbcServices getJdbcServices() {
return jdbcServices; return jdbcServices;
@ -555,25 +544,12 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
return metamodel.getTypeConfiguration().getTypeResolver(); return metamodel.getTypeConfiguration().getTypeResolver();
} }
public QueryPlanCache getQueryPlanCache() {
return queryPlanCache;
}
private Map<String,HibernateException> checkNamedQueries() throws HibernateException {
return namedQueryRepository.checkNamedQueries( queryPlanCache );
}
@Override @Override
public DeserializationResolver getDeserializationResolver() { public DeserializationResolver getDeserializationResolver() {
return new DeserializationResolver() { return (DeserializationResolver) () -> (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.findSessionFactory(
@Override uuid,
public SessionFactoryImplementor resolve() { name
return (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.findSessionFactory( );
uuid,
name
);
}
};
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -702,12 +678,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
); );
} }
@Override
public NamedQueryRepository getNamedQueryRepository() {
return namedQueryRepository;
}
public Type getIdentifierType(String className) throws MappingException { public Type getIdentifierType(String className) throws MappingException {
return getMetamodel().entityPersister( className ).getIdentifierType(); return getMetamodel().entityPersister( className ).getIdentifierType();
} }
@ -715,18 +685,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
return getMetamodel().entityPersister( className ).getIdentifierPropertyName(); return getMetamodel().entityPersister( className ).getIdentifierPropertyName();
} }
public Type[] getReturnTypes(String queryString) throws HibernateException {
final ReturnMetadata metadata = queryPlanCache.getHQLQueryPlan( queryString, false, Collections.EMPTY_MAP )
.getReturnMetadata();
return metadata == null ? null : metadata.getReturnTypes();
}
public String[] getReturnAliases(String queryString) throws HibernateException {
final ReturnMetadata metadata = queryPlanCache.getHQLQueryPlan( queryString, false, Collections.EMPTY_MAP )
.getReturnMetadata();
return metadata == null ? null : metadata.getReturnAliases();
}
public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException { public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException {
return getClassMetadata( persistentClass.getName() ); return getClassMetadata( persistentClass.getName() );
} }
@ -800,9 +758,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
metamodel.close(); metamodel.close();
} }
if ( queryPlanCache != null ) { queryEngine.close();
queryPlanCache.cleanup();
}
if ( delayedDropAction != null ) { if ( delayedDropAction != null ) {
delayedDropAction.perform( serviceRegistry ); delayedDropAction.perform( serviceRegistry );
@ -839,31 +795,34 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
// first, handle StoredProcedureQuery // first, handle StoredProcedureQuery
try { try {
final ProcedureCall unwrapped = query.unwrap( ProcedureCall.class ); final ProcedureCallImplementor unwrapped = query.unwrap( ProcedureCallImplementor.class );
if ( unwrapped != null ) { if ( unwrapped != null ) {
addNamedStoredProcedureQuery( name, unwrapped ); getQueryEngine().getNamedQueryRepository().registerCallableQueryMemento(
name,
unwrapped.toMemento( name )
);
return; return;
} }
} }
catch ( PersistenceException ignore ) { catch ( PersistenceException ignore ) {
// this means 'query' is not a StoredProcedureQueryImpl // this means 'query' is not a ProcedureCallImplementor
} }
// then try as a native-SQL or JPQL query // then try as a native-SQL or JPQL query
try { try {
org.hibernate.query.Query hibernateQuery = query.unwrap( org.hibernate.query.Query.class ); QueryImplementor<?> hibernateQuery = query.unwrap( QueryImplementor.class );
if ( hibernateQuery != null ) { if ( hibernateQuery != null ) {
// create and register the proper NamedQueryDefinition... // create and register the proper NamedQueryDefinition...
if ( NativeQuery.class.isInstance( hibernateQuery ) ) { if ( hibernateQuery instanceof NativeQueryImplementor ) {
getNamedQueryRepository().registerNamedSQLQueryDefinition( getQueryEngine().getNamedQueryRepository().registerNativeQueryMemento(
name, name,
extractSqlQueryDefinition( (NativeQuery) hibernateQuery, name ) ( (NativeQueryImplementor) hibernateQuery ).toMemento( name )
); );
} }
else { else {
getNamedQueryRepository().registerNamedQueryDefinition( getQueryEngine().getNamedQueryRepository().registerHqlQueryMemento(
name, name,
extractHqlQueryDefinition( hibernateQuery, name ) ( ( HqlQueryImplementor ) hibernateQuery ).toMemento( name )
); );
} }
return; return;
@ -882,56 +841,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
); );
} }
private void addNamedStoredProcedureQuery(String name, ProcedureCall procedureCall) {
getNamedQueryRepository().registerNamedProcedureCallMemento(
name,
procedureCall.extractMemento( procedureCall.getHints() )
);
}
private NamedSQLQueryDefinition extractSqlQueryDefinition(org.hibernate.query.NativeQuery nativeSqlQuery, String name) {
final NamedNativeQueryMementoBuilder builder = new NamedNativeQueryMementoBuilder( name );
fillInNamedQueryBuilder( builder, nativeSqlQuery );
builder.setCallable( nativeSqlQuery.isCallable() )
.setQuerySpaces( nativeSqlQuery.getSynchronizedQuerySpaces() )
.setQueryReturns( nativeSqlQuery.getQueryReturns() );
return builder.createNamedQueryDefinition();
}
private NamedHqlQueryMementoImpl extractHqlQueryDefinition(org.hibernate.query.Query hqlQuery, String name) {
final NamedHqlQueryMemento.Builder builder = new NamedHqlQueryMemento.Builder( name );
fillInNamedQueryBuilder( builder, hqlQuery );
// LockOptions only valid for HQL/JPQL queries...
builder.setLockOptions( hqlQuery.getLockOptions().makeCopy() );
return builder.createNamedQueryDefinition();
}
private void fillInNamedQueryBuilder(NamedHqlQueryMemento.Builder builder, org.hibernate.query.Query query) {
builder.setQuery( query.getQueryString() )
.setComment( query.getComment() )
.setCacheable( query.isCacheable() )
.setCacheRegion( query.getCacheRegion() )
.setCacheMode( query.getCacheMode() )
.setReadOnly( query.isReadOnly() )
.setFlushMode( query.getHibernateFlushMode() );
if ( query.getQueryOptions().getFirstRow() != null ) {
builder.setFirstResult( query.getQueryOptions().getFirstRow() );
}
if ( query.getQueryOptions().getMaxRows() != null ) {
builder.setMaxResults( query.getQueryOptions().getMaxRows() );
}
if ( query.getQueryOptions().getTimeout() != null ) {
builder.setTimeout( query.getQueryOptions().getTimeout() );
}
if ( query.getQueryOptions().getFetchSize() != null ) {
builder.setFetchSize( query.getQueryOptions().getFetchSize() );
}
}
@Override @Override
public <T> T unwrap(Class<T> type) { public <T> T unwrap(Class<T> type) {
if ( type.isAssignableFrom( SessionFactory.class ) ) { if ( type.isAssignableFrom( SessionFactory.class ) ) {
@ -1038,6 +947,16 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
} }
} }
@Override
public JpaMetamodel getJpaMetamodel() {
return getMetamodel().getJpaMetamodel();
}
@Override
public Integer getMaximumFetchDepth() {
return getSessionFactoryOptions().getMaximumFetchDepth();
}
@Override @Override
public ServiceRegistryImplementor getServiceRegistry() { public ServiceRegistryImplementor getServiceRegistry() {
return serviceRegistry; return serviceRegistry;
@ -1061,7 +980,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
} }
@Override @Override
public Type resolveParameterBindType(Object bindValue) { public AllowableParameterType<?> resolveParameterBindType(Object bindValue) {
if ( bindValue == null ) { if ( bindValue == null ) {
// we can't guess // we can't guess
return null; return null;
@ -1071,27 +990,8 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
} }
@Override @Override
public Type resolveParameterBindType(Class clazz){ public AllowableParameterType<?> resolveParameterBindType(Class<?> javaType) {
String typename = clazz.getName(); return getMetamodel().resolveQueryParameterType( javaType );
Type type = getTypeResolver().heuristicType( typename );
boolean serializable = type != null && type instanceof SerializableType;
if ( type == null || serializable ) {
try {
getMetamodel().entityPersister( clazz.getName() );
}
catch (MappingException me) {
if ( serializable ) {
return type;
}
else {
throw new HibernateException( "Could not determine a type for class: " + typename );
}
}
return getTypeHelper().entity( clazz );
}
else {
return type;
}
} }
public static Interceptor configuredInterceptor(Interceptor interceptor, SessionFactoryOptions options) { public static Interceptor configuredInterceptor(Interceptor interceptor, SessionFactoryOptions options) {

View File

@ -41,12 +41,12 @@ public class SessionFactoryRegistry {
/** /**
* A map for mapping the UUID of a SessionFactory to the corresponding SessionFactory instance * A map for mapping the UUID of a SessionFactory to the corresponding SessionFactory instance
*/ */
private final ConcurrentHashMap<String, SessionFactory> sessionFactoryMap = new ConcurrentHashMap<String, SessionFactory>(); private final ConcurrentHashMap<String, SessionFactoryImplementor> sessionFactoryMap = new ConcurrentHashMap<>();
/** /**
* A cross-reference for mapping a SessionFactory name to its UUID. Not all SessionFactories get named, * A cross-reference for mapping a SessionFactory name to its UUID. Not all SessionFactories get named,
*/ */
private final ConcurrentHashMap<String, String> nameUuidXref = new ConcurrentHashMap<String, String>(); private final ConcurrentHashMap<String, String> nameUuidXref = new ConcurrentHashMap<>();
private SessionFactoryRegistry() { private SessionFactoryRegistry() {
LOG.debugf( "Initializing SessionFactoryRegistry : %s", this ); LOG.debugf( "Initializing SessionFactoryRegistry : %s", this );
@ -65,7 +65,7 @@ public class SessionFactoryRegistry {
String uuid, String uuid,
String name, String name,
boolean isNameAlsoJndiName, boolean isNameAlsoJndiName,
SessionFactory instance, SessionFactoryImplementor instance,
JndiService jndiService) { JndiService jndiService) {
if ( uuid == null ) { if ( uuid == null ) {
throw new IllegalArgumentException( "SessionFactory UUID cannot be null" ); throw new IllegalArgumentException( "SessionFactory UUID cannot be null" );
@ -143,16 +143,16 @@ public class SessionFactoryRegistry {
* *
* @return The SessionFactory * @return The SessionFactory
*/ */
public SessionFactory getNamedSessionFactory(String name) { public SessionFactoryImplementor getNamedSessionFactory(String name) {
LOG.debugf( "Lookup: name=%s", name ); LOG.debugf( "Lookup: name=%s", name );
final String uuid = nameUuidXref.get( name ); final String uuid = nameUuidXref.get( name );
// protect against NPE -- see HHH-8428 // protect against NPE -- see HHH-8428
return uuid == null ? null : getSessionFactory( uuid ); return uuid == null ? null : getSessionFactory( uuid );
} }
public SessionFactory getSessionFactory(String uuid) { public SessionFactoryImplementor getSessionFactory(String uuid) {
LOG.debugf( "Lookup: uid=%s", uuid ); LOG.debugf( "Lookup: uid=%s", uuid );
final SessionFactory sessionFactory = sessionFactoryMap.get( uuid ); final SessionFactoryImplementor sessionFactory = sessionFactoryMap.get( uuid );
if ( sessionFactory == null && LOG.isDebugEnabled() ) { if ( sessionFactory == null && LOG.isDebugEnabled() ) {
LOG.debugf( "Not found: %s", uuid ); LOG.debugf( "Not found: %s", uuid );
LOG.debug( sessionFactoryMap.toString() ); LOG.debug( sessionFactoryMap.toString() );
@ -160,8 +160,8 @@ public class SessionFactoryRegistry {
return sessionFactory; return sessionFactory;
} }
public SessionFactory findSessionFactory(String uuid, String name) { public SessionFactoryImplementor findSessionFactory(String uuid, String name) {
SessionFactory sessionFactory = getSessionFactory( uuid ); SessionFactoryImplementor sessionFactory = getSessionFactory( uuid );
if ( sessionFactory == null && StringHelper.isNotEmpty( name ) ) { if ( sessionFactory == null && StringHelper.isNotEmpty( name ) ) {
sessionFactory = getNamedSessionFactory( name ); sessionFactory = getNamedSessionFactory( name );
} }
@ -205,10 +205,13 @@ public class SessionFactoryRegistry {
LOG.factoryUnboundFromName( jndiName ); LOG.factoryUnboundFromName( jndiName );
final String uuid = nameUuidXref.remove( jndiName ); final String uuid = nameUuidXref.remove( jndiName );
//noinspection StatementWithEmptyBody
if ( uuid == null ) { if ( uuid == null ) {
// serious problem... but not sure what to do yet // serious problem... but not sure what to do yet
} }
sessionFactoryMap.remove( uuid ); else {
sessionFactoryMap.remove( uuid );
}
} }
@Override @Override

View File

@ -1691,7 +1691,7 @@ public final class SessionImpl
if ( roleAfterFlush == null ) { if ( roleAfterFlush == null ) {
throw new QueryException( "The collection was unreferenced" ); throw new QueryException( "The collection was unreferenced" );
} }
plan = factory.getQueryPlanCache().getFilterQueryPlan( plan = factory.getQueryInterpretationCache().getFilterQueryPlan(
filter, filter,
roleAfterFlush.getRole(), roleAfterFlush.getRole(),
shallow, shallow,
@ -1701,7 +1701,7 @@ public final class SessionImpl
else { else {
// otherwise, we only need to flush if there are in-memory changes // otherwise, we only need to flush if there are in-memory changes
// to the queried tables // to the queried tables
plan = factory.getQueryPlanCache().getFilterQueryPlan( plan = factory.getQueryInterpretationCache().getFilterQueryPlan(
filter, filter,
roleBeforeFlush.getRole(), roleBeforeFlush.getRole(),
shallow, shallow,
@ -1716,7 +1716,7 @@ public final class SessionImpl
if ( roleAfterFlush == null ) { if ( roleAfterFlush == null ) {
throw new QueryException( "The collection was dereferenced" ); throw new QueryException( "The collection was dereferenced" );
} }
plan = factory.getQueryPlanCache().getFilterQueryPlan( plan = factory.getQueryInterpretationCache().getFilterQueryPlan(
filter, filter,
roleAfterFlush.getRole(), roleAfterFlush.getRole(),
shallow, shallow,
@ -2106,7 +2106,7 @@ public final class SessionImpl
log.tracev( "Scroll SQL query: {0}", customQuery.getSQL() ); log.tracev( "Scroll SQL query: {0}", customQuery.getSQL() );
} }
CustomLoader loader = getFactory().getQueryPlanCache().getNativeQueryInterpreter().createCustomLoader( customQuery, getFactory() ); CustomLoader loader = getFactory().getQueryInterpretationCache().getNativeQueryInterpreter().createCustomLoader( customQuery, getFactory() );
autoFlushIfRequired( loader.getQuerySpaces() ); autoFlushIfRequired( loader.getQuerySpaces() );
@ -2130,7 +2130,7 @@ public final class SessionImpl
log.tracev( "SQL query: {0}", customQuery.getSQL() ); log.tracev( "SQL query: {0}", customQuery.getSQL() );
} }
CustomLoader loader = getFactory().getQueryPlanCache().getNativeQueryInterpreter().createCustomLoader( customQuery, getFactory() ); CustomLoader loader = getFactory().getQueryInterpretationCache().getNativeQueryInterpreter().createCustomLoader( customQuery, getFactory() );
autoFlushIfRequired( loader.getQuerySpaces() ); autoFlushIfRequired( loader.getQuerySpaces() );

View File

@ -34,6 +34,8 @@ public interface AllowableOutputParameterType<J> extends AllowableParameterType<
*/ */
SqlTypeDescriptor getSqlTypeDescriptor(); SqlTypeDescriptor getSqlTypeDescriptor();
/** /**
* Perform the extraction * Perform the extraction
* *

View File

@ -14,8 +14,8 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.model.domain.AllowableOutputParameterType; import org.hibernate.metamodel.model.domain.AllowableOutputParameterType;
import org.hibernate.metamodel.model.domain.AllowableParameterType; import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.procedure.spi.FunctionReturnImplementor; import org.hibernate.procedure.spi.FunctionReturnImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.ProcedureCallImplementor; import org.hibernate.procedure.spi.ProcedureCallImplementor;
import org.hibernate.query.QueryParameter;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -108,17 +108,13 @@ public class FunctionReturnImpl implements FunctionReturnImplementor {
} }
@Override @Override
public ParameterMemento toMemento() { public NamedCallableQueryMemento.ParameterMemento toMemento() {
// todo (6.0) : do we need a FunctionReturnMemento? return session -> {
return new ParameterMemento() { if ( ormType != null ) {
@Override return new FunctionReturnImpl( procedureCall, ormType );
public QueryParameter toQueryParameter(SharedSessionContractImplementor session) { }
if ( ormType != null ) { else {
return new FunctionReturnImpl( procedureCall, ormType ); return new FunctionReturnImpl( procedureCall, jdbcTypeCode );
}
else {
return new FunctionReturnImpl( procedureCall, jdbcTypeCode );
}
} }
}; };
} }

View File

@ -19,7 +19,7 @@ import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.spi.NamedCallableQueryMemento; import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.ParameterStrategy; import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor; import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.AbstractNamedQueryMemento; import org.hibernate.query.spi.AbstractNamedQueryMemento;
import org.hibernate.query.spi.NamedQueryMemento; import org.hibernate.query.spi.NamedQueryMemento;
@ -32,7 +32,7 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
private final String callableName; private final String callableName;
private final ParameterStrategy parameterStrategy; private final ParameterStrategy parameterStrategy;
private final List<ParameterMemento> parameterMementos; private final List<NamedCallableQueryMemento.ParameterMemento> parameterMementos;
private final String[] resultSetMappingNames; private final String[] resultSetMappingNames;
private final Class[] resultSetMappingClasses; private final Class[] resultSetMappingClasses;
@ -47,7 +47,7 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
String name, String name,
String callableName, String callableName,
ParameterStrategy parameterStrategy, ParameterStrategy parameterStrategy,
List<ParameterMemento> parameterMementos, List<NamedCallableQueryMemento.ParameterMemento> parameterMementos,
String[] resultSetMappingNames, String[] resultSetMappingNames,
Class[] resultSetMappingClasses, Class[] resultSetMappingClasses,
Set<String> querySpaces, Set<String> querySpaces,
@ -86,7 +86,7 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
} }
@Override @Override
public List<ParameterMemento> getParameterMementos() { public List<NamedCallableQueryMemento.ParameterMemento> getParameterMementos() {
return parameterMementos; return parameterMementos;
} }
@ -140,7 +140,7 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
/** /**
* A "disconnected" copy of the metadata for a parameter, that can be used in ProcedureCallMementoImpl. * A "disconnected" copy of the metadata for a parameter, that can be used in ProcedureCallMementoImpl.
*/ */
public static class ParameterMementoImpl implements ParameterMemento { public static class ParameterMementoImpl implements NamedCallableQueryMemento.ParameterMemento {
private final Integer position; private final Integer position;
private final String name; private final String name;
private final ParameterMode mode; private final ParameterMode mode;

View File

@ -1,129 +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.procedure.internal;
import javax.persistence.ParameterMode;
import javax.persistence.TemporalType;
import org.hibernate.procedure.ParameterBind;
import org.hibernate.query.internal.BindingTypeHelper;
import org.hibernate.query.procedure.internal.ProcedureParamBindings;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* Implementation of the {@link ParameterBind} contract.
*
* @author Steve Ebersole
*/
public class ParameterBindImpl<T> implements ParameterBind<T> {
private static final Logger log = Logger.getLogger( ParameterBindImpl.class );
private final ProcedureParameterImplementor procedureParameter;
private final ProcedureParamBindings procedureParamBindings;
private boolean isBound;
private T value;
private Type hibernateType;
private TemporalType explicitTemporalType;
public ParameterBindImpl(
ProcedureParameterImplementor procedureParameter,
ProcedureParamBindings procedureParamBindings) {
this.procedureParameter = procedureParameter;
this.procedureParamBindings = procedureParamBindings;
this.hibernateType = procedureParameter.getHibernateType();
}
@Override
public T getValue() {
return value;
}
@Override
public TemporalType getExplicitTemporalType() {
return explicitTemporalType;
}
@Override
public boolean isBound() {
return isBound;
}
@Override
public void setBindValue(T value) {
internalSetValue( value );
if ( value != null && hibernateType == null ) {
hibernateType = procedureParamBindings.getProcedureCall()
.getSession()
.getFactory()
.getTypeResolver()
.heuristicType( value.getClass().getName() );
log.debugf( "Using heuristic type [%s] based on bind value [%s] as `bindType`", hibernateType, value );
}
}
private void internalSetValue(T value) {
if ( procedureParameter.getMode() != ParameterMode.IN && procedureParameter.getMode() != ParameterMode.INOUT ) {
throw new IllegalStateException( "Can only bind values for IN/INOUT parameters : " + procedureParameter );
}
if ( procedureParameter.getParameterType() != null ) {
if ( value == null ) {
if ( !procedureParameter.isPassNullsEnabled() ) {
throw new IllegalArgumentException( "The parameter " +
( procedureParameter.getName() != null
? "named [" + procedureParameter.getName() + "]"
: "at position [" + procedureParameter.getPosition() + "]" )
+ " was null. You need to call ParameterRegistration#enablePassingNulls(true) in order to pass null parameters." );
}
}
else if ( !procedureParameter.getParameterType().isInstance( value ) &&
!procedureParameter.getHibernateType().getReturnedClass().isInstance( value ) ) {
throw new IllegalArgumentException( "Bind value [" + value + "] was not of specified type [" + procedureParameter
.getParameterType() );
}
}
this.value = value;
this.isBound = true;
}
@Override
public void setBindValue(T value, Type clarifiedType) {
internalSetValue( value );
this.hibernateType = clarifiedType;
log.debugf( "Using explicit type [%s] as `bindType`", hibernateType, value );
}
@Override
public void setBindValue(T value, TemporalType clarifiedTemporalType) {
internalSetValue( value );
this.hibernateType = BindingTypeHelper.INSTANCE.determineTypeForTemporalType( clarifiedTemporalType, hibernateType, value );
this.explicitTemporalType = clarifiedTemporalType;
log.debugf( "Using type [%s] (based on TemporalType [%s] as `bindType`", hibernateType, clarifiedTemporalType );
}
@Override
public T getBindValue() {
if ( !isBound ) {
throw new IllegalStateException( "Value not yet bound" );
}
return value;
}
@Override
public Type getBindType() {
return hibernateType;
}
}

View File

@ -45,14 +45,11 @@ import org.hibernate.procedure.ProcedureOutputs;
import org.hibernate.procedure.spi.NamedCallableQueryMemento; import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.ParameterStrategy; import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.procedure.spi.ProcedureCallImplementor; import org.hibernate.procedure.spi.ProcedureCallImplementor;
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.Query; import org.hibernate.query.Query;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.internal.QueryOptionsImpl; import org.hibernate.query.internal.QueryOptionsImpl;
import org.hibernate.query.procedure.ProcedureParameter; import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.query.procedure.internal.ProcedureParamBindings;
import org.hibernate.query.procedure.internal.ProcedureParameterImpl;
import org.hibernate.query.procedure.internal.ProcedureParameterMetadataImpl;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.AbstractQuery; import org.hibernate.query.spi.AbstractQuery;
import org.hibernate.query.spi.MutableQueryOptions; import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
@ -108,8 +105,8 @@ public class ProcedureCallImpl<R>
super( session ); super( session );
this.procedureName = procedureName; this.procedureName = procedureName;
this.parameterMetadata = new ProcedureParameterMetadataImpl( this ); this.parameterMetadata = new ProcedureParameterMetadataImpl();
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this ); this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.synchronizedQuerySpaces = null; this.synchronizedQuerySpaces = null;
this.domainResultProducers = null; this.domainResultProducers = null;
@ -128,8 +125,8 @@ public class ProcedureCallImpl<R>
this.procedureName = procedureName; this.procedureName = procedureName;
this.parameterMetadata = new ProcedureParameterMetadataImpl( this ); this.parameterMetadata = new ProcedureParameterMetadataImpl();
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this ); this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.domainResultProducers = CollectionHelper.arrayList( resultClasses.length ); this.domainResultProducers = CollectionHelper.arrayList( resultClasses.length );
this.synchronizedQuerySpaces = new HashSet<>(); this.synchronizedQuerySpaces = new HashSet<>();
@ -159,8 +156,8 @@ public class ProcedureCallImpl<R>
this.procedureName = procedureName; this.procedureName = procedureName;
this.parameterMetadata = new ProcedureParameterMetadataImpl( this ); this.parameterMetadata = new ProcedureParameterMetadataImpl();
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this ); this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.domainResultProducers = CollectionHelper.arrayList( resultSetMappingNames.length ); this.domainResultProducers = CollectionHelper.arrayList( resultSetMappingNames.length );
this.synchronizedQuerySpaces = new HashSet<>(); this.synchronizedQuerySpaces = new HashSet<>();
@ -183,8 +180,8 @@ public class ProcedureCallImpl<R>
super( session ); super( session );
this.procedureName = memento.getCallableName(); this.procedureName = memento.getCallableName();
this.parameterMetadata = new ProcedureParameterMetadataImpl( this, memento ); this.parameterMetadata = new ProcedureParameterMetadataImpl( memento, session );
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this ); this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.domainResultProducers = new ArrayList<>(); this.domainResultProducers = new ArrayList<>();
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() ); this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
@ -240,6 +237,11 @@ public class ProcedureCallImpl<R>
return this; return this;
} }
@Override
public QueryParameterBindings getParameterBindings() {
return paramBindings;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DomainParameterBindingContext // DomainParameterBindingContext
@ -299,13 +301,11 @@ public class ProcedureCallImpl<R>
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> ProcedureParameter<T> registerParameter(int position, Class<T> javaType, ParameterMode mode) { public <T> ProcedureParameter<T> registerParameter(int position, Class<T> javaType, ParameterMode mode) {
final ProcedureParameterImpl procedureParameter = new ProcedureParameterImpl( final ProcedureParameterImpl procedureParameter = new ProcedureParameterImpl(
this,
position, position,
mode, mode,
javaType, javaType,
getSession().getFactory().getMetamodel().resolveQueryParameterType( javaType ) getSessionFactory().getDomainModel().resolveQueryParameterType( javaType )
); );
registerParameter( procedureParameter ); registerParameter( procedureParameter );
return procedureParameter; return procedureParameter;
} }
@ -328,13 +328,12 @@ public class ProcedureCallImpl<R>
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> ProcedureParameterImplementor<T> registerParameter(String name, Class<T> type, ParameterMode mode) { public <T> ProcedureParameterImplementor<T> registerParameter(String name, Class<T> javaType, ParameterMode mode) {
final ProcedureParameterImpl parameter = new ProcedureParameterImpl( final ProcedureParameterImpl parameter = new ProcedureParameterImpl(
this,
name, name,
mode, mode,
type, javaType,
getSession().getFactory().getMetamodel().resolveQueryParameterType( type ) getSessionFactory().getDomainModel().resolveQueryParameterType( javaType )
); );
registerParameter( parameter ); registerParameter( parameter );
@ -408,7 +407,7 @@ public class ProcedureCallImpl<R>
public void accept(QueryParameter queryParameter) { public void accept(QueryParameter queryParameter) {
try { try {
final ProcedureParameterImplementor registration = (ProcedureParameterImplementor) queryParameter; final ProcedureParameterImplementor registration = (ProcedureParameterImplementor) queryParameter;
registration.prepare( statement, i ); registration.prepare( statement, i, ProcedureCallImpl.this );
if ( registration.getMode() == ParameterMode.REF_CURSOR ) { if ( registration.getMode() == ParameterMode.REF_CURSOR ) {
i++; i++;
} }
@ -525,14 +524,14 @@ public class ProcedureCallImpl<R>
); );
} }
private static List<NamedCallableQueryMementoImpl.ParameterMemento> toParameterMementos( private static List<NamedCallableQueryMemento.ParameterMemento> toParameterMementos(
ProcedureParameterMetadataImpl parameterMetadata) { ProcedureParameterMetadataImpl parameterMetadata) {
if ( parameterMetadata.getParameterStrategy() == ParameterStrategy.UNKNOWN ) { if ( parameterMetadata.getParameterStrategy() == ParameterStrategy.UNKNOWN ) {
// none... // none...
return Collections.emptyList(); return Collections.emptyList();
} }
final List<NamedCallableQueryMementoImpl.ParameterMemento> mementos = new ArrayList<>(); final List<NamedCallableQueryMemento.ParameterMemento> mementos = new ArrayList<>();
parameterMetadata.visitRegistrations( parameterMetadata.visitRegistrations(
queryParameter -> { queryParameter -> {
@ -922,5 +921,4 @@ public class ProcedureCallImpl<R>
public ProcedureCallImplementor<R> setParameter(int position, Date value, TemporalType temporalPrecision) { public ProcedureCallImplementor<R> setParameter(int position, Date value, TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision ); return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision );
} }
} }

View File

@ -8,15 +8,18 @@ package org.hibernate.procedure.internal;
import java.sql.CallableStatement; import java.sql.CallableStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.util.List; import java.sql.SQLException;
import java.util.function.Supplier;
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport; import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
import org.hibernate.procedure.ParameterRegistration; import org.hibernate.metamodel.model.domain.AllowableOutputParameterType;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.procedure.ParameterMisuseException;
import org.hibernate.procedure.ProcedureOutputs; import org.hibernate.procedure.ProcedureOutputs;
import org.hibernate.procedure.spi.ParameterRegistrationImplementor; import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.result.Output; import org.hibernate.result.Output;
import org.hibernate.result.internal.OutputsImpl; import org.hibernate.result.internal.OutputsImpl;
import org.hibernate.sql.exec.ExecutionException;
/** /**
* Implementation of ProcedureResult. Defines centralized access to all of the results of a procedure call. * Implementation of ProcedureResult. Defines centralized access to all of the results of a procedure call.
@ -27,7 +30,7 @@ public class ProcedureOutputsImpl extends OutputsImpl implements ProcedureOutput
private final ProcedureCallImpl procedureCall; private final ProcedureCallImpl procedureCall;
private final CallableStatement callableStatement; private final CallableStatement callableStatement;
private final ParameterRegistrationImplementor[] refCursorParameters; private final ProcedureParameterImplementor[] refCursorParameters;
private int refCursorParamIndex; private int refCursorParamIndex;
ProcedureOutputsImpl(ProcedureCallImpl procedureCall, CallableStatement callableStatement) { ProcedureOutputsImpl(ProcedureCallImpl procedureCall, CallableStatement callableStatement) {
@ -39,18 +42,34 @@ public class ProcedureOutputsImpl extends OutputsImpl implements ProcedureOutput
} }
@Override @Override
public <T> T getOutputParameterValue(ParameterRegistration<T> parameterRegistration) { public <T> T getOutputParameterValue(ProcedureParameter<T> parameter) {
return ( (ParameterRegistrationImplementor<T>) parameterRegistration ).extract( callableStatement ); final AllowableParameterType<T> hibernateType = parameter.getHibernateType();
if ( hibernateType instanceof AllowableOutputParameterType<?> ) {
try {
//noinspection unchecked
return (T) ( (AllowableOutputParameterType<?>) hibernateType ).extract(
callableStatement,
parameter.getPosition(),
procedureCall.getSession()
);
}
catch (SQLException e) {
throw new ExecutionException( "Error extracting procedure output parameter value [" + parameter + "]", e );
}
}
else {
throw new ParameterMisuseException( "Parameter type cannot extract procedure output parameters" );
}
} }
@Override @Override
public Object getOutputParameterValue(String name) { public Object getOutputParameterValue(String name) {
return procedureCall.getParameterRegistration( name ).extract( callableStatement ); return getOutputParameterValue( procedureCall.getParameterMetadata().getQueryParameter( name ) );
} }
@Override @Override
public Object getOutputParameterValue(int position) { public Object getOutputParameterValue(int position) {
return procedureCall.getParameterRegistration( position ).extract( callableStatement ); return getOutputParameterValue( procedureCall.getParameterMetadata().getQueryParameter( position ) );
} }
@Override @Override
@ -80,7 +99,7 @@ public class ProcedureOutputsImpl extends OutputsImpl implements ProcedureOutput
@Override @Override
protected Output buildExtendedReturn() { protected Output buildExtendedReturn() {
ProcedureOutputsImpl.this.refCursorParamIndex++; ProcedureOutputsImpl.this.refCursorParamIndex++;
final ParameterRegistrationImplementor refCursorParam = ProcedureOutputsImpl.this.refCursorParameters[refCursorParamIndex]; final ProcedureParameterImplementor refCursorParam = ProcedureOutputsImpl.this.refCursorParameters[refCursorParamIndex];
ResultSet resultSet; ResultSet resultSet;
if ( refCursorParam.getName() != null ) { if ( refCursorParam.getName() != null ) {
resultSet = ProcedureOutputsImpl.this.procedureCall.getSession().getFactory().getServiceRegistry() resultSet = ProcedureOutputsImpl.this.procedureCall.getSession().getFactory().getServiceRegistry()

View File

@ -1,20 +1,21 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.query.procedure.internal; package org.hibernate.procedure.internal;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.persistence.ParameterMode; import javax.persistence.ParameterMode;
import org.hibernate.procedure.internal.ParameterBindImpl;
import org.hibernate.procedure.internal.ProcedureCallImpl;
import org.hibernate.query.procedure.ProcedureParameterBinding; import org.hibernate.query.procedure.ProcedureParameterBinding;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor; import org.hibernate.procedure.spi.ProcedureParameterBindingImplementor;
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindingTypeResolver;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.QueryParameterImplementor;
@ -23,23 +24,25 @@ import org.hibernate.query.spi.QueryParameterImplementor;
*/ */
public class ProcedureParamBindings implements QueryParameterBindings { public class ProcedureParamBindings implements QueryParameterBindings {
private final ProcedureParameterMetadataImpl parameterMetadata; private final ProcedureParameterMetadataImpl parameterMetadata;
private final ProcedureCallImpl procedureCall; private final QueryParameterBindingTypeResolver typeResolver;
private final Map<ProcedureParameterImplementor<?>, ProcedureParameterBinding<?>> bindingMap = new HashMap<>(); private final Map<ProcedureParameterImplementor<?>, ProcedureParameterBindingImplementor<?>> bindingMap = new HashMap<>();
public ProcedureParamBindings( public ProcedureParamBindings(
ProcedureParameterMetadataImpl parameterMetadata, ProcedureParameterMetadataImpl parameterMetadata,
ProcedureCallImpl procedureCall) { QueryParameterBindingTypeResolver typeResolver) {
this.parameterMetadata = parameterMetadata; this.parameterMetadata = parameterMetadata;
this.procedureCall = procedureCall; this.typeResolver = typeResolver;
} }
public ProcedureParameterMetadataImpl getParameterMetadata() { public ProcedureParameterMetadataImpl getParameterMetadata() {
return parameterMetadata; return parameterMetadata;
} }
public ProcedureCallImpl getProcedureCall() { @Override
return procedureCall; public boolean isBound(QueryParameterImplementor<?> parameter) {
//noinspection SuspiciousMethodCalls
return bindingMap.containsKey( parameter );
} }
@Override @Override
@ -47,16 +50,17 @@ public class ProcedureParamBindings implements QueryParameterBindings {
return getBinding( parameterMetadata.resolve( parameter ) ); return getBinding( parameterMetadata.resolve( parameter ) );
} }
public QueryParameterBinding<?> getBinding(ProcedureParameterImplementor parameter) { public ProcedureParameterBindingImplementor<?> getBinding(ProcedureParameterImplementor<?> parameter) {
final ProcedureParameterImplementor procParam = parameterMetadata.resolve( parameter ); final ProcedureParameterImplementor procParam = parameterMetadata.resolve( parameter );
ProcedureParameterBinding binding = bindingMap.get( procParam ); ProcedureParameterBindingImplementor binding = bindingMap.get( procParam );
if ( binding == null ) { if ( binding == null ) {
if ( ! parameterMetadata.containsReference( parameter ) ) { if ( ! parameterMetadata.containsReference( parameter ) ) {
throw new IllegalArgumentException( "Passed parameter is not registered with this query" ); throw new IllegalArgumentException( "Passed parameter is not registered with this query" );
} }
binding = new ParameterBindImpl( procParam, this ); //noinspection unchecked
binding = new ProcedureParameterBindingImpl( procParam, typeResolver );
bindingMap.put( procParam, binding ); bindingMap.put( procParam, binding );
} }
@ -65,7 +69,7 @@ public class ProcedureParamBindings implements QueryParameterBindings {
@Override @Override
public ProcedureParameterBinding<?> getBinding(String name) { public ProcedureParameterBinding<?> getBinding(String name) {
return getBinding( parameterMetadata.getQueryParameter( name ) ); return (ProcedureParameterBinding<?>) getBinding( parameterMetadata.getQueryParameter( name ) );
} }
@Override @Override
@ -74,7 +78,7 @@ public class ProcedureParamBindings implements QueryParameterBindings {
} }
@Override @Override
public void verifyParametersBound(boolean callable) { public void validate() {
parameterMetadata.visitRegistrations( parameterMetadata.visitRegistrations(
queryParameter -> { queryParameter -> {
final ProcedureParameterImplementor procParam = (ProcedureParameterImplementor) queryParameter; final ProcedureParameterImplementor procParam = (ProcedureParameterImplementor) queryParameter;
@ -89,4 +93,10 @@ public class ProcedureParamBindings implements QueryParameterBindings {
); );
} }
@Override
public boolean hasAnyMultiValuedBindings() {
return false;
}
} }

View File

@ -9,8 +9,8 @@ package org.hibernate.procedure.internal;
import org.hibernate.metamodel.model.domain.AllowableParameterType; import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.query.internal.QueryParameterBindingImpl; import org.hibernate.query.internal.QueryParameterBindingImpl;
import org.hibernate.query.procedure.ProcedureParameterBinding; import org.hibernate.query.procedure.ProcedureParameterBinding;
import org.hibernate.query.procedure.spi.ProcedureParameterBindingImplementor; import org.hibernate.procedure.spi.ProcedureParameterBindingImplementor;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor; import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.QueryParameterBindingTypeResolver; import org.hibernate.query.spi.QueryParameterBindingTypeResolver;
/** /**

View File

@ -6,13 +6,22 @@
*/ */
package org.hibernate.procedure.internal; package org.hibernate.procedure.internal;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.util.Objects; import java.util.Objects;
import javax.persistence.ParameterMode; import javax.persistence.ParameterMode;
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
import org.hibernate.metamodel.model.domain.AllowableParameterType; import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.metamodel.model.domain.AllowableTemporalParameterType;
import org.hibernate.procedure.spi.NamedCallableQueryMemento; import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.procedure.spi.ProcedureCallImplementor;
import org.hibernate.query.AbstractQueryParameter; import org.hibernate.query.AbstractQueryParameter;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor; import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.type.ProcedureParameterExtractionAware;
import org.hibernate.type.ProcedureParameterNamedBinder;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -111,4 +120,124 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
public int hashCode() { public int hashCode() {
return Objects.hash( name, position, mode ); return Objects.hash( name, position, mode );
} }
@Override
public void prepare(
CallableStatement statement,
int startIndex,
ProcedureCallImplementor<?> procedureCall) throws SQLException {
final QueryParameterBinding<?> binding = procedureCall.getParameterBindings().getBinding( this );
// initially set up the Type we will use for binding as the explicit type.
AllowableParameterType typeToUse = getHibernateType();
// however, for Calendar binding with an explicit TemporalType we may need to adjust this...
if ( binding != null && binding.getExplicitTemporalPrecision() != null ) {
typeToUse = ( (AllowableTemporalParameterType) typeToUse ).resolveTemporalPrecision(
binding.getExplicitTemporalPrecision(),
procedureCall.getSession().getFactory().getTypeConfiguration()
);
}
this.startIndex = startIndex;
if ( mode == ParameterMode.IN || mode == ParameterMode.INOUT || mode == ParameterMode.OUT ) {
if ( mode == ParameterMode.INOUT || mode == ParameterMode.OUT ) {
if ( sqlTypesToUse.length > 1 ) {
// there is more than one column involved; see if the Hibernate Type can handle
// multi-param extraction...
final boolean canHandleMultiParamExtraction =
ProcedureParameterExtractionAware.class.isInstance( typeToUse )
&& ( (ProcedureParameterExtractionAware) typeToUse ).canDoExtraction();
if ( ! canHandleMultiParamExtraction ) {
// it cannot...
throw new UnsupportedOperationException(
"Type [" + typeToUse + "] does support multi-parameter value extraction"
);
}
}
// TODO: sqlTypesToUse.length > 1 does not seem to have a working use case (HHH-10769).
// The idea is that an embeddable/custom type can have more than one column values
// that correspond with embeddable/custom attribute value. This does not seem to
// be working yet. For now, if sqlTypesToUse.length > 1, then register
// the out parameters by position (since we only have one name).
// This will cause a failure if there are other parameters bound by
// name and the dialect does not support "mixed" named/positional parameters;
// e.g., Oracle.
if ( sqlTypesToUse.length == 1 &&
procedureCall.getParameterStrategy() == ParameterStrategy.NAMED &&
canDoNameParameterBinding( typeToUse ) ) {
statement.registerOutParameter( getName(), sqlTypesToUse[0] );
}
else {
for ( int i = 0; i < sqlTypesToUse.length; i++ ) {
statement.registerOutParameter( startIndex + i, sqlTypesToUse[i] );
}
}
}
if ( mode == ParameterMode.INOUT || mode == ParameterMode.IN ) {
if ( binding == null || binding.getBindValue() == null ) {
// the user did not binding a value to the parameter being processed. This is the condition
// defined by `passNulls` and that value controls what happens here. If `passNulls` is
// {@code true} we will binding the NULL value into the statement; if `passNulls` is
// {@code false} we will not.
//
// Unfortunately there is not a way to reliably know through JDBC metadata whether a procedure
// parameter defines a default value. Deferring to that information would be the best option
if ( isPassNullsEnabled() ) {
log.debugf(
"Stored procedure [%s] IN/INOUT parameter [%s] not bound and `passNulls` was set to true; binding NULL",
procedureCall.getProcedureName(),
this
);
if ( procedureCall.getParameterStrategy() == ParameterStrategy.NAMED && canDoNameParameterBinding( typeToUse ) ) {
((ProcedureParameterNamedBinder) typeToUse).nullSafeSet(
statement,
null,
this.getName(),
procedureCall.getSession()
);
}
else {
typeToUse.nullSafeSet( statement, null, startIndex, procedureCall.getSession() );
}
}
else {
log.debugf(
"Stored procedure [%s] IN/INOUT parameter [%s] not bound and `passNulls` was set to false; assuming procedure defines default value",
procedureCall.getProcedureName(),
this
);
}
}
else {
if ( procedureCall.getParameterStrategy() == ParameterStrategy.NAMED && canDoNameParameterBinding( typeToUse ) ) {
((ProcedureParameterNamedBinder) typeToUse).nullSafeSet(
statement,
binding.getBindValue(),
this.getName(),
procedureCall.getSession()
);
}
else {
typeToUse.nullSafeSet( statement, binding.getBindValue(), startIndex, procedureCall.getSession() );
}
}
}
}
else {
// we have a REF_CURSOR type param
if ( procedureCall.getParameterStrategy() == ParameterStrategy.NAMED ) {
procedureCall.getSession().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.registerRefCursorParameter( statement, getName() );
}
else {
procedureCall.getSession().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.registerRefCursorParameter( statement, startIndex );
}
}
}
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.query.procedure.internal; package org.hibernate.procedure.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -13,35 +13,35 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import javax.persistence.Parameter; import javax.persistence.Parameter;
import org.hibernate.procedure.internal.ProcedureCallImpl; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento; import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.ParameterStrategy; import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.procedure.ProcedureParameter; import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor; import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.ParameterMetadataImplementor; import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.QueryParameterImplementor;
/** /**
* Specialized ParameterMetadataImplementor for callable queries implementing
* expandable parameter registrations
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ProcedureParameterMetadataImpl implements ParameterMetadataImplementor { public class ProcedureParameterMetadataImpl implements ParameterMetadataImplementor {
private final ProcedureCallImpl procedureCall;
private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN; private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN;
private List<ProcedureParameterImplementor<?>> parameters = new ArrayList<>(); private List<ProcedureParameterImplementor<?>> parameters;
public ProcedureParameterMetadataImpl(ProcedureCallImpl procedureCall) { @SuppressWarnings("WeakerAccess")
this.procedureCall = procedureCall; public ProcedureParameterMetadataImpl() {
} }
public <R> ProcedureParameterMetadataImpl(ProcedureCallImpl procedureCall, NamedCallableQueryMemento memento) { @SuppressWarnings("WeakerAccess")
this( procedureCall ); public ProcedureParameterMetadataImpl(NamedCallableQueryMemento memento, SharedSessionContractImplementor session) {
memento.getParameterMementos().forEach( memento.getParameterMementos().forEach(
parameterMemento -> registerParameter( parameterMemento.resolve( procedureCall.getSession() ) ) parameterMemento -> registerParameter( parameterMemento.resolve( session ) )
); );
} }
@ -69,6 +69,13 @@ public class ProcedureParameterMetadataImpl implements ParameterMetadataImplemen
parameters.add( parameter ); parameters.add( parameter );
} }
@Override
public void visitParameters(Consumer<QueryParameterImplementor<?>> consumer) {
if ( parameters != null ) {
parameters.forEach( consumer );
}
}
@Override @Override
public boolean hasNamedParameters() { public boolean hasNamedParameters() {
return parameterStrategy == ParameterStrategy.NAMED; return parameterStrategy == ParameterStrategy.NAMED;
@ -105,15 +112,11 @@ public class ProcedureParameterMetadataImpl implements ParameterMetadataImplemen
return parameters.contains( parameter ); return parameters.contains( parameter );
} }
@SuppressWarnings("WeakerAccess")
public ParameterStrategy getParameterStrategy() { public ParameterStrategy getParameterStrategy() {
return parameterStrategy; return parameterStrategy;
} }
@Override
public void collectAllParameters(ParameterCollector collector) {
parameters.forEach( collector::collect );
}
@Override @Override
public boolean hasAnyMatching(Predicate<QueryParameterImplementor<?>> filter) { public boolean hasAnyMatching(Predicate<QueryParameterImplementor<?>> filter) {
if ( parameters.isEmpty() ) { if ( parameters.isEmpty() ) {

View File

@ -10,8 +10,9 @@ import java.sql.CallableStatement;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.procedure.internal.FunctionReturnImpl; import org.hibernate.procedure.internal.FunctionReturnImpl;
import org.hibernate.query.procedure.internal.ProcedureParamBindings; import org.hibernate.procedure.internal.ProcedureParamBindings;
import org.hibernate.query.spi.ParameterMetadataImplementor; import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.sql.exec.spi.JdbcCall;
/** /**
* @author Steve Ebersole * @author Steve Ebersole

View File

@ -7,7 +7,6 @@
package org.hibernate.procedure.spi; package org.hibernate.procedure.spi;
import org.hibernate.procedure.FunctionReturn; import org.hibernate.procedure.FunctionReturn;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
/** /**
* @author Steve Ebersole * @author Steve Ebersole

View File

@ -14,7 +14,6 @@ import org.hibernate.Session;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.NamedQueryMemento; import org.hibernate.query.spi.NamedQueryMemento;
/** /**
@ -70,7 +69,7 @@ public interface NamedCallableQueryMemento extends NamedQueryMemento {
*/ */
ProcedureCall makeProcedureCall(SharedSessionContractImplementor session); ProcedureCall makeProcedureCall(SharedSessionContractImplementor session);
interface ParameterMemento { interface ParameterMemento extends NamedQueryMemento.ParameterMemento {
ProcedureParameterImplementor resolve(SharedSessionContractImplementor session); ProcedureParameterImplementor resolve(SharedSessionContractImplementor session);
} }
} }

View File

@ -26,6 +26,8 @@ public interface ProcedureCallImplementor<R> extends ProcedureCall, QueryImpleme
return list(); return list();
} }
ParameterStrategy getParameterStrategy();
@Override @Override
default R getSingleResult() { default R getSingleResult() {
return uniqueResult(); return uniqueResult();

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.query.procedure.spi; package org.hibernate.procedure.spi;
import org.hibernate.query.procedure.ProcedureParameterBinding; import org.hibernate.query.procedure.ProcedureParameterBinding;

View File

@ -0,0 +1,33 @@
/*
* 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.procedure.spi;
import java.sql.CallableStatement;
import java.sql.SQLException;
import org.hibernate.Incubating;
import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.query.spi.QueryParameterImplementor;
/**
* SPI extension for ProcedureParameter
*
* @author Steve Ebersole
*/
@Incubating
public interface ProcedureParameterImplementor<T> extends ProcedureParameter<T>, QueryParameterImplementor<T> {
/**
* Allow the parameter to register itself with the JDBC CallableStatement,
* if necessary, as well as perform any other needed preparation for exeuction
*
* @throws SQLException Indicates a problem with any underlying JDBC calls
*/
void prepare(
CallableStatement statement,
int startIndex,
ProcedureCallImplementor<?> callImplementor) throws SQLException;
}

View File

@ -6,11 +6,13 @@
*/ */
package org.hibernate.query; package org.hibernate.query;
import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
/** /**
* User hook for applying transformations of the query result tuples (the result "row"). * User hook for applying transformations of the query result tuples (the result "row").
* *
* Ultimately, gets wrapped in a * Ultimately, gets wrapped in a
* {@link org.hibernate.sql.exec.internal.RowTransformerTupleTransformerAdapter} * {@link RowTransformerTupleTransformerAdapter}
* to adapt the TupleTransformer to the {@link org.hibernate.sql.exec.spi.RowTransformer} * to adapt the TupleTransformer to the {@link org.hibernate.sql.exec.spi.RowTransformer}
* contract, which is the thing actually used to process the results internally. * contract, which is the thing actually used to process the results internally.
* *

View File

@ -1666,7 +1666,7 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
} }
private boolean isSelect() { private boolean isSelect() {
return getProducer().getFactory().getQueryPlanCache() return getProducer().getFactory().getQueryInterpretationCache()
.getHQLQueryPlan( getQueryString(), false, Collections.<String, Filter>emptyMap() ) .getHQLQueryPlan( getQueryString(), false, Collections.<String, Filter>emptyMap() )
.isSelect(); .isSelect();
} }

View File

@ -19,7 +19,7 @@ import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.spi.NamedQueryRepository; import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.query.spi.NamedResultSetMappingMemento; import org.hibernate.query.spi.NamedResultSetMappingMemento;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento; import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
@ -131,8 +131,8 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
Map<String,HibernateException> errors = new HashMap<>(); Map<String,HibernateException> errors = new HashMap<>();
final SemanticQueryProducer sqmProducer = queryEngine.getSemanticQueryProducer(); final SemanticQueryProducer sqmProducer = queryEngine.getSemanticQueryProducer();
final QueryPlanCache queryPlanCache = queryEngine.getQueryPlanCache(); final QueryInterpretationCache interpretationCache = queryEngine.getInterpretationCache();
final boolean cachingEnabled = queryPlanCache.isEnabled(); final boolean cachingEnabled = interpretationCache.isEnabled();
// Check named HQL queries // Check named HQL queries
log.debugf( "Checking %s named HQL queries", hqlMementoMap.size() ); log.debugf( "Checking %s named HQL queries", hqlMementoMap.size() );
@ -144,7 +144,7 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
if ( cachingEnabled ) { if ( cachingEnabled ) {
// todo (6.0) : need to cache these; however atm that requires producing a SqmQueryImpl // todo (6.0) : need to cache these; however atm that requires producing a SqmQueryImpl
// queryEngine.getQueryPlanCache().getHQLQueryPlan( hqlMemento.getQueryString(), false, Collections.EMPTY_MAP ); // queryEngine.getQueryInterpretationCache().getHQLQueryPlan( hqlMemento.getQueryString(), false, Collections.EMPTY_MAP );
} }
} }
catch ( HibernateException e ) { catch ( HibernateException e ) {

View File

@ -160,14 +160,8 @@ public class ParameterMetadataImpl implements ParameterMetadataImplementor {
} }
@Override @Override
public void visitRegistrations(Consumer<? extends QueryParameter<?>> action) { public void visitParameters(Consumer<QueryParameterImplementor<?>> consumer) {
//noinspection unchecked queryParameters.forEach( consumer );
queryParameters.forEach( (Consumer) action );
}
@Override
public void collectAllParameters(ParameterCollector collector) {
queryParameters.forEach( collector::collect );
} }
@Override @Override

View File

@ -9,18 +9,18 @@ package org.hibernate.query.internal;
import java.util.function.Function; import java.util.function.Function;
import org.hibernate.query.spi.NonSelectQueryPlan; import org.hibernate.query.spi.NonSelectQueryPlan;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.spi.SelectQueryPlan; import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class QueryPlanCacheDisabledImpl implements QueryPlanCache { public class QueryInterpretationCacheDisabledImpl implements QueryInterpretationCache {
/** /**
* Singleton access * Singleton access
*/ */
public static final QueryPlanCacheDisabledImpl INSTANCE = new QueryPlanCacheDisabledImpl(); public static final QueryInterpretationCacheDisabledImpl INSTANCE = new QueryInterpretationCacheDisabledImpl();
@Override @Override
public SelectQueryPlan getSelectQueryPlan(Key key) { public SelectQueryPlan getSelectQueryPlan(Key key) {

View File

@ -12,7 +12,7 @@ import org.hibernate.internal.util.collections.BoundedConcurrentHashMap;
import org.hibernate.query.QueryLogger; import org.hibernate.query.QueryLogger;
import org.hibernate.query.spi.NonSelectQueryPlan; import org.hibernate.query.spi.NonSelectQueryPlan;
import org.hibernate.query.spi.QueryPlan; import org.hibernate.query.spi.QueryPlan;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.spi.SelectQueryPlan; import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
@ -23,7 +23,7 @@ import org.jboss.logging.Logger;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class QueryPlanCacheStandardImpl implements QueryPlanCache { public class QueryInterpretationCacheStandardImpl implements QueryInterpretationCache {
private static final Logger log = QueryLogger.subLogger( "plan.cache" ); private static final Logger log = QueryLogger.subLogger( "plan.cache" );
/** /**
@ -41,7 +41,7 @@ public class QueryPlanCacheStandardImpl implements QueryPlanCache {
private final BoundedConcurrentHashMap<Key, QueryPlan> queryPlanCache; private final BoundedConcurrentHashMap<Key, QueryPlan> queryPlanCache;
private final BoundedConcurrentHashMap<String, SqmStatement<?>> sqmStatementCache; private final BoundedConcurrentHashMap<String, SqmStatement<?>> sqmStatementCache;
public QueryPlanCacheStandardImpl(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 );
@ -88,13 +88,13 @@ public class QueryPlanCacheStandardImpl implements QueryPlanCache {
@Override @Override
public SqmStatement getSqmStatement(String queryString) { public SqmStatement getSqmStatement(String queryString) {
log.debugf( "Creating and caching SqmStatement - %s", queryString ); log.tracef( "#getSqmStatement( %s )", queryString );
return sqmStatementCache.get( queryString ); return sqmStatementCache.get( queryString );
} }
@Override @Override
public void cacheSqmStatement(String queryString, SqmStatement sqmStatement) { public void cacheSqmStatement(String queryString, SqmStatement sqmStatement) {
log.debugf( "Creating and caching SqmStatement - %s", queryString ); log.tracef( "#cacheSqmStatement( %s )", queryString );
// todo (6.0) : Log and stats, see HHH-12855 // todo (6.0) : Log and stats, see HHH-12855
sqmStatementCache.putIfAbsent( queryString, sqmStatement ); sqmStatementCache.putIfAbsent( queryString, sqmStatement );
} }

View File

@ -22,7 +22,6 @@ import org.hibernate.type.spi.TypeConfiguration;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> { public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
private final QueryParameter<T> queryParameter;
private final QueryParameterBindingTypeResolver typeResolver; private final QueryParameterBindingTypeResolver typeResolver;
private final boolean isBindingValidationRequired; private final boolean isBindingValidationRequired;
@ -30,6 +29,7 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
private boolean isMultiValued; private boolean isMultiValued;
private AllowableParameterType<T> bindType; private AllowableParameterType<T> bindType;
private TemporalType explicitTemporalPrecision;
private T bindValue; private T bindValue;
private Collection<T> bindValues; private Collection<T> bindValues;
@ -40,7 +40,6 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
QueryParameter<T> queryParameter, QueryParameter<T> queryParameter,
QueryParameterBindingTypeResolver typeResolver, QueryParameterBindingTypeResolver typeResolver,
boolean isBindingValidationRequired) { boolean isBindingValidationRequired) {
this.queryParameter = queryParameter;
this.typeResolver = typeResolver; this.typeResolver = typeResolver;
this.isBindingValidationRequired = isBindingValidationRequired; this.isBindingValidationRequired = isBindingValidationRequired;
this.bindType = queryParameter.getHibernateType(); this.bindType = queryParameter.getHibernateType();
@ -51,7 +50,6 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
QueryParameterBindingTypeResolver typeResolver, QueryParameterBindingTypeResolver typeResolver,
AllowableParameterType<T> bindType, AllowableParameterType<T> bindType,
boolean isBindingValidationRequired) { boolean isBindingValidationRequired) {
this.queryParameter = queryParameter;
this.typeResolver = typeResolver; this.typeResolver = typeResolver;
this.isBindingValidationRequired = isBindingValidationRequired; this.isBindingValidationRequired = isBindingValidationRequired;
this.bindType = bindType; this.bindType = bindType;
@ -62,6 +60,11 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
return bindType; return bindType;
} }
@Override
public TemporalType getExplicitTemporalPrecision() {
return explicitTemporalPrecision;
}
@Override @Override
public boolean isBound() { public boolean isBound() {
return isBound; return isBound;
@ -99,7 +102,8 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
this.bindValue = value; this.bindValue = value;
if ( bindType == null ) { if ( bindType == null ) {
this.bindType = typeResolver.resolveParameterBindType( value ); //noinspection unchecked
this.bindType = (AllowableParameterType) typeResolver.resolveParameterBindType( value );
} }
} }
@ -129,6 +133,8 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
getBindType().getJavaType(), getBindType().getJavaType(),
getBindType() getBindType()
); );
this.explicitTemporalPrecision = temporalTypePrecision;
} }
@ -153,7 +159,8 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
this.bindValues = values; this.bindValues = values;
if ( bindType == null && !values.isEmpty() ) { if ( bindType == null && !values.isEmpty() ) {
this.bindType = typeResolver.resolveParameterBindType( values.iterator().next() ); //noinspection unchecked
this.bindType = (AllowableParameterType) typeResolver.resolveParameterBindType( values.iterator().next() );
} }
} }
@ -173,12 +180,13 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T> {
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
setBindValues( values ); setBindValues( values );
final Object exampleValue = values.isEmpty() ? null : values.iterator().next();
this.bindType = BindingTypeHelper.INSTANCE.resolveTemporalPrecision( this.bindType = BindingTypeHelper.INSTANCE.resolveTemporalPrecision(
temporalTypePrecision, temporalTypePrecision,
bindType, bindType,
typeConfiguration typeConfiguration
); );
this.explicitTemporalPrecision = temporalTypePrecision;
} }

View File

@ -1,32 +1,60 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.query.internal; package org.hibernate.query.internal;
import org.hibernate.query.QueryParameter; import java.util.Objects;
import org.hibernate.type.Type;
import org.hibernate.metamodel.model.mapping.spi.AllowableParameterType;
import org.hibernate.query.named.spi.ParameterMemento;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
/** /**
* Models a named query parameter * QueryParameter impl for named-parameters in HQL, JPQL or Criteria queries.
*
* NOTE: Unfortunately we need to model named and positional parameters separately still until 6.0
*
* NOTE : Also, notice that this still treats JPA "positional" parameters as named. This will change in
* 6.0 as well after we remove support for legacy positional parameters (the JPA model is better there).
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class QueryParameterNamedImpl<T> extends AbstractQueryParameterImpl<T> implements QueryParameter<T> { public class QueryParameterNamedImpl<T> extends AbstractQueryParameter<T> {
private final String name; /**
private final int[] sourceLocations; * Create a named parameter descriptor from the SQM parameter
*
* @param parameter The source parameter info
*
* @return The parameter descriptor
*/
public static <T> QueryParameterNamedImpl<T> fromSqm(SqmParameter parameter) {
assert parameter.getName() != null;
assert parameter.getPosition() == null;
public QueryParameterNamedImpl(String name, int[] sourceLocations, Type expectedType) { return new QueryParameterNamedImpl<T>(
super( expectedType ); parameter.getName(),
parameter.allowMultiValuedBinding(),
parameter.getAnticipatedType() != null ?
(AllowableParameterType) parameter.getAnticipatedType() :
null
);
}
public static <T> QueryParameterNamedImpl<T> fromNativeQuery(String name) {
return new QueryParameterNamedImpl<T>(
name,
false,
null
);
}
private final String name;
private QueryParameterNamedImpl(
String name,
boolean allowMultiValuedBinding,
AllowableParameterType anticipatedType) {
super( allowMultiValuedBinding, anticipatedType );
this.name = name; this.name = name;
this.sourceLocations = sourceLocations;
} }
@Override @Override
@ -35,13 +63,8 @@ public class QueryParameterNamedImpl<T> extends AbstractQueryParameterImpl<T> im
} }
@Override @Override
public Integer getPosition() { public ParameterMemento toMemento() {
return null; return session -> new QueryParameterNamedImpl( getName(), allowsMultiValuedBinding(), getHibernateType() );
}
@Override
public int[] getSourceLocations() {
return sourceLocations;
} }
@Override @Override
@ -52,13 +75,12 @@ public class QueryParameterNamedImpl<T> extends AbstractQueryParameterImpl<T> im
if ( o == null || getClass() != o.getClass() ) { if ( o == null || getClass() != o.getClass() ) {
return false; return false;
} }
QueryParameterNamedImpl<?> that = (QueryParameterNamedImpl<?>) o; QueryParameterNamedImpl<?> that = (QueryParameterNamedImpl<?>) o;
return getName().equals( that.getName() ); return Objects.equals( name, that.name );
} }
@Override @Override
public int hashCode() { public int hashCode() {
return getName().hashCode(); return Objects.hash( name );
} }
} }

View File

@ -0,0 +1,86 @@
/*
* 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.internal;
import java.util.Objects;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.query.AbstractQueryParameter;
import org.hibernate.query.spi.NamedQueryMemento;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
/**
* QueryParameter impl for positional-parameters in HQL, JPQL or Criteria queries.
*
* @author Steve Ebersole
*/
public class QueryParameterPositionalImpl<T> extends AbstractQueryParameter<T> {
private final int position;
/**
* Create a positional parameter descriptor from the SQM parameter
*
* @param parameter The source parameter info
*
* @return The parameter descriptor
*/
public static <T> QueryParameterPositionalImpl<T> fromSqm(SqmParameter<T> parameter) {
assert parameter.getPosition() != null;
assert parameter.getName() == null;
return new QueryParameterPositionalImpl<T>(
parameter.getPosition(),
parameter.allowMultiValuedBinding(),
parameter.getAnticipatedType()
);
}
public static <T> QueryParameterPositionalImpl<T> fromNativeQuery(int position) {
return new QueryParameterPositionalImpl<T>(
position,
false,
null
);
}
public QueryParameterPositionalImpl(
Integer position,
boolean allowMultiValuedBinding,
AllowableParameterType<T> anticipatedType) {
super( allowMultiValuedBinding, anticipatedType );
this.position = position;
}
@Override
public Integer getPosition() {
return position;
}
@Override
public NamedQueryMemento.ParameterMemento toMemento() {
return session -> new QueryParameterPositionalImpl( getPosition(), allowsMultiValuedBinding(), getHibernateType() );
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
QueryParameterPositionalImpl<?> that = (QueryParameterPositionalImpl<?>) o;
return position == that.position;
}
@Override
public int hashCode() {
return Objects.hash( position );
}
}

View File

@ -1,321 +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.query.procedure.internal;
import java.sql.CallableStatement;
import java.sql.SQLException;
import javax.persistence.ParameterMode;
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.metamodel.model.domain.AllowableOutputParameterType;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.metamodel.model.domain.AllowableTemporalParameterType;
import org.hibernate.procedure.ParameterMisuseException;
import org.hibernate.procedure.internal.ProcedureCallImpl;
import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.query.internal.AbstractQueryParameterImpl;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.type.ProcedureParameterExtractionAware;
import org.hibernate.type.ProcedureParameterNamedBinder;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class ProcedureParameterImpl<T>
extends AbstractQueryParameterImpl<T>
implements ProcedureParameterImplementor<T> {
private static final Logger log = Logger.getLogger( ProcedureParameterImpl.class );
private final ProcedureCallImpl procedureCall;
private final String name;
private final Integer position;
private final ParameterMode mode;
private final Class<T> javaType;
// in-flight state needed between prepare and extract
private int startIndex;
public ProcedureParameterImpl(
ProcedureCallImpl procedureCall,
String name,
ParameterMode mode,
Class<T> javaType,
AllowableParameterType<T> hibernateType) {
super( hibernateType );
this.procedureCall = procedureCall;
this.name = name;
this.position = null;
this.mode = mode;
this.javaType = javaType;
setHibernateType( hibernateType );
}
public ProcedureParameterImpl(
ProcedureCallImpl procedureCall,
Integer position,
ParameterMode mode,
Class<T> javaType,
AllowableParameterType<T> hibernateType) {
super( hibernateType );
this.procedureCall = procedureCall;
this.name = null;
this.position = position;
this.mode = mode;
this.javaType = javaType;
setHibernateType( hibernateType );
}
@Override
public ParameterMode getMode() {
return mode;
}
@Override
public String getName() {
return name;
}
@Override
public Integer getPosition() {
return position;
}
@Override
public void setHibernateType(AllowableParameterType<?> expectedType) {
super.setHibernateType( expectedType );
if ( mode == ParameterMode.REF_CURSOR || mode == ParameterMode.INOUT || mode == ParameterMode.OUT ) {
if ( ! ( expectedType instanceof AllowableOutputParameterType ) ) {
throw new IllegalArgumentException( "Passed type must implement AllowableOutputParameterType" );
}
}
}
@Override
public void prepare(CallableStatement statement, int startIndex) throws SQLException {
final QueryParameterBinding<?> binding = procedureCall.getQueryParameterBindings().getBinding( this );
// initially set up the Type we will use for binding as the explicit type.
AllowableParameterType typeToUse = getHibernateType();
// however, for Calendar binding with an explicit TemporalType we may need to adjust this...
if ( binding != null && binding.getExplicitTemporalPrecision() != null ) {
typeToUse = ( (AllowableTemporalParameterType) typeToUse ).resolveTemporalPrecision(
binding.getExplicitTemporalPrecision(),
procedureCall.getSession().getFactory().getTypeConfiguration()
);
}
this.startIndex = startIndex;
if ( mode == ParameterMode.IN || mode == ParameterMode.INOUT || mode == ParameterMode.OUT ) {
if ( mode == ParameterMode.INOUT || mode == ParameterMode.OUT ) {
if ( sqlTypesToUse.length > 1 ) {
// there is more than one column involved; see if the Hibernate Type can handle
// multi-param extraction...
final boolean canHandleMultiParamExtraction =
ProcedureParameterExtractionAware.class.isInstance( typeToUse )
&& ( (ProcedureParameterExtractionAware) typeToUse ).canDoExtraction();
if ( ! canHandleMultiParamExtraction ) {
// it cannot...
throw new UnsupportedOperationException(
"Type [" + typeToUse + "] does support multi-parameter value extraction"
);
}
}
// TODO: sqlTypesToUse.length > 1 does not seem to have a working use case (HHH-10769).
// The idea is that an embeddable/custom type can have more than one column values
// that correspond with embeddable/custom attribute value. This does not seem to
// be working yet. For now, if sqlTypesToUse.length > 1, then register
// the out parameters by position (since we only have one name).
// This will cause a failure if there are other parameters bound by
// name and the dialect does not support "mixed" named/positional parameters;
// e.g., Oracle.
if ( sqlTypesToUse.length == 1 &&
procedureCall.getParameterStrategy() == ParameterStrategy.NAMED &&
canDoNameParameterBinding( typeToUse ) ) {
statement.registerOutParameter( getName(), sqlTypesToUse[0] );
}
else {
for ( int i = 0; i < sqlTypesToUse.length; i++ ) {
statement.registerOutParameter( startIndex + i, sqlTypesToUse[i] );
}
}
}
if ( mode == ParameterMode.INOUT || mode == ParameterMode.IN ) {
if ( binding == null || binding.getValue() == null ) {
// the user did not binding a value to the parameter being processed. This is the condition
// defined by `passNulls` and that value controls what happens here. If `passNulls` is
// {@code true} we will binding the NULL value into the statement; if `passNulls` is
// {@code false} we will not.
//
// Unfortunately there is not a way to reliably know through JDBC metadata whether a procedure
// parameter defines a default value. Deferring to that information would be the best option
if ( isPassNullsEnabled() ) {
log.debugf(
"Stored procedure [%s] IN/INOUT parameter [%s] not bound and `passNulls` was set to true; binding NULL",
procedureCall.getProcedureName(),
this
);
if ( this.procedureCall.getParameterStrategy() == ParameterStrategy.NAMED && canDoNameParameterBinding( typeToUse ) ) {
((ProcedureParameterNamedBinder) typeToUse).nullSafeSet(
statement,
null,
this.getName(),
procedureCall.getSession()
);
}
else {
typeToUse.nullSafeSet( statement, null, startIndex, procedureCall.getSession() );
}
}
else {
log.debugf(
"Stored procedure [%s] IN/INOUT parameter [%s] not bound and `passNulls` was set to false; assuming procedure defines default value",
procedureCall.getProcedureName(),
this
);
}
}
else {
if ( this.procedureCall.getParameterStrategy() == ParameterStrategy.NAMED && canDoNameParameterBinding( typeToUse ) ) {
((ProcedureParameterNamedBinder) typeToUse).nullSafeSet(
statement,
binding.getValue(),
this.getName(),
procedureCall.getSession()
);
}
else {
typeToUse.nullSafeSet( statement, binding.getValue(), startIndex, procedureCall.getSession() );
}
}
}
}
else {
// we have a REF_CURSOR type param
if ( procedureCall.getParameterStrategy() == ParameterStrategy.NAMED ) {
procedureCall.getSession().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.registerRefCursorParameter( statement, getName() );
}
else {
procedureCall.getSession().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.registerRefCursorParameter( statement, startIndex );
}
}
}
private boolean canDoNameParameterBinding(Type hibernateType) {
final ExtractedDatabaseMetaData databaseMetaData = procedureCall.getSession()
.getJdbcCoordinator()
.getJdbcSessionOwner()
.getJdbcSessionContext()
.getServiceRegistry().getService( JdbcEnvironment.class )
.getExtractedDatabaseMetaData();
return
databaseMetaData.supportsNamedParameters()
&& ProcedureParameterNamedBinder.class.isInstance( hibernateType )
&& ((ProcedureParameterNamedBinder) hibernateType).canDoSetting();
}
private Type determineHibernateType() {
final ParameterBind<T> bind = getBind();
// if the bind defines a type, that should be the most specific...
final Type bindType = bind.getBindType();
if ( bindType != null ) {
return bindType;
}
// Next, see if the parameter itself has an expected type, and if so use that...
final Type paramType = getHibernateType();
if ( paramType != null ) {
return paramType;
}
// here we just have guessing games
if ( bind.getValue() != null ) {
return procedureCall.getSession()
.getFactory()
.getTypeResolver()
.heuristicType( bind.getValue().getClass().getName() );
}
throw new IllegalStateException( "Unable to determine SQL type(s) - Hibernate Type not known" );
}
@Override
@SuppressWarnings("unchecked")
public T extract(CallableStatement statement) {
if ( mode == ParameterMode.IN ) {
throw new ParameterMisuseException( "IN parameter not valid for output extraction" );
}
try {
if ( mode == ParameterMode.REF_CURSOR ) {
if ( procedureCall.getParameterStrategy() == ParameterStrategy.NAMED ) {
return (T) statement.getObject( name );
}
else {
return (T) statement.getObject( startIndex );
}
}
else {
final Type hibernateType = determineHibernateType();
final int[] sqlTypes = hibernateType.sqlTypes( procedureCall.getSession().getFactory() );
// TODO: sqlTypesToUse.length > 1 does not seem to have a working use case (HHH-10769).
// For now, if sqlTypes.length > 1 with a named parameter, then extract
// parameter values by position (since we only have one name).
final boolean useNamed = sqlTypes.length == 1 &&
procedureCall.getParameterStrategy() == ParameterStrategy.NAMED &&
canDoNameParameterBinding( hibernateType );
if ( ProcedureParameterExtractionAware.class.isInstance( hibernateType ) ) {
if ( useNamed ) {
return (T) ( (ProcedureParameterExtractionAware) hibernateType ).extract(
statement,
new String[] { getName() },
procedureCall.getSession()
);
}
else {
return (T) ( (ProcedureParameterExtractionAware) hibernateType ).extract(
statement,
startIndex,
procedureCall.getSession()
);
}
}
else {
if ( useNamed ) {
return (T) statement.getObject( name );
}
else {
return (T) statement.getObject( startIndex );
}
}
}
}
catch (SQLException e) {
throw procedureCall.getSession().getFactory().getSQLExceptionHelper().convert(
e,
"Unable to extract OUT/INOUT parameter value"
);
}
}
}

View File

@ -1,29 +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.query.procedure.spi;
import java.sql.CallableStatement;
import java.sql.SQLException;
import org.hibernate.Incubating;
import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.query.spi.QueryParameterImplementor;
/**
* NOTE: Consider this contract (and its sub-contracts) as incubating as we transition to 6.0 and SQM
*
* @author Steve Ebersole
*/
@Incubating
public interface ProcedureParameterImplementor<T> extends ProcedureParameter<T>, QueryParameterImplementor<T> {
void prepare(CallableStatement statement, int startIndex) throws SQLException;
@Override
default boolean allowsMultiValuedBinding() {
return false;
}
}

View File

@ -10,6 +10,7 @@ import java.util.Map;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
/** /**
* Named Query mementos are stored in the QueryEngine's * Named Query mementos are stored in the QueryEngine's
@ -46,4 +47,8 @@ public interface NamedQueryMemento {
String getComment(); String getComment();
Map<String, Object> getHints(); Map<String, Object> getHints();
interface ParameterMemento {
QueryParameterImplementor resolve(SharedSessionContractImplementor session);
}
} }

View File

@ -6,30 +6,38 @@
*/ */
package org.hibernate.query.spi; package org.hibernate.query.spi;
import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import javax.persistence.Parameter; import javax.persistence.Parameter;
import org.hibernate.query.ParameterMetadata; import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryParameter;
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface ParameterMetadataImplementor extends ParameterMetadata { public interface ParameterMetadataImplementor extends ParameterMetadata {
@FunctionalInterface void visitParameters(Consumer<QueryParameterImplementor<?>> consumer);
interface ParameterCollector {
<P extends QueryParameterImplementor<?>> void collect(P queryParameter); default void collectAllParameters(Consumer<QueryParameterImplementor<?>> collector) {
visitParameters( collector );
} }
void collectAllParameters(ParameterCollector collector); @Override
default void visitRegistrations(Consumer<? extends QueryParameter<?>> action) {
//noinspection unchecked
visitParameters( (Consumer) action );
}
boolean hasAnyMatching(Predicate<QueryParameterImplementor<?>> filter); boolean hasAnyMatching(Predicate<QueryParameterImplementor<?>> filter);
@Override @Override
QueryParameterImplementor<?> getQueryParameter(String name); ProcedureParameterImplementor<?> getQueryParameter(String name);
@Override @Override
QueryParameterImplementor<?> getQueryParameter(int positionLabel); ProcedureParameterImplementor<?> getQueryParameter(int positionLabel);
@Override @Override
QueryParameterImplementor<?> resolve(Parameter param); ProcedureParameterImplementor<?> resolve(Parameter param);
} }

View File

@ -10,6 +10,7 @@ import java.util.Map;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
@ -17,8 +18,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.query.QueryLogger; import org.hibernate.query.QueryLogger;
import org.hibernate.query.internal.QueryPlanCacheDisabledImpl; import org.hibernate.query.internal.QueryInterpretationCacheDisabledImpl;
import org.hibernate.query.internal.QueryPlanCacheStandardImpl; import org.hibernate.query.internal.QueryInterpretationCacheStandardImpl;
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder; import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
import org.hibernate.query.hql.SemanticQueryProducer; import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry; import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
@ -38,7 +39,7 @@ import org.hibernate.service.ServiceRegistry;
public class QueryEngine { public class QueryEngine {
public static QueryEngine from( public static QueryEngine from(
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
NamedQueryRepository namedQueryRepository) { MetadataImplementor metadata) {
return new QueryEngine( return new QueryEngine(
sessionFactory.getMetamodel(), sessionFactory.getMetamodel(),
sessionFactory.getServiceRegistry(), sessionFactory.getServiceRegistry(),
@ -46,14 +47,14 @@ public class QueryEngine {
sessionFactory, sessionFactory,
new SqmCreationOptionsStandard( sessionFactory ), new SqmCreationOptionsStandard( sessionFactory ),
sessionFactory.getProperties(), sessionFactory.getProperties(),
namedQueryRepository metadata.buildNamedQueryRepository( sessionFactory )
); );
} }
private final NamedQueryRepository namedQueryRepository; private final NamedQueryRepository namedQueryRepository;
private final SqmCriteriaNodeBuilder criteriaBuilder; private final SqmCriteriaNodeBuilder criteriaBuilder;
private final SemanticQueryProducer semanticQueryProducer; private final SemanticQueryProducer semanticQueryProducer;
private final QueryPlanCache queryPlanCache; private final QueryInterpretationCache interpretationCache;
private final SqmFunctionRegistry sqmFunctionRegistry; private final SqmFunctionRegistry sqmFunctionRegistry;
public QueryEngine( public QueryEngine(
@ -72,7 +73,7 @@ public class QueryEngine {
serviceRegistry serviceRegistry
); );
this.queryPlanCache = buildQueryPlanCache( properties ); this.interpretationCache = buildQueryPlanCache( properties );
this.sqmFunctionRegistry = new SqmFunctionRegistry(); this.sqmFunctionRegistry = new SqmFunctionRegistry();
serviceRegistry.getService( JdbcServices.class ) serviceRegistry.getService( JdbcServices.class )
@ -80,9 +81,11 @@ public class QueryEngine {
.getDialect() .getDialect()
.initializeFunctionRegistry( this ); .initializeFunctionRegistry( this );
runtimeOptions.getSqmFunctionRegistry().overlay( sqmFunctionRegistry ); runtimeOptions.getSqmFunctionRegistry().overlay( sqmFunctionRegistry );
getNamedQueryRepository().checkNamedQueries( this );
} }
private static QueryPlanCache buildQueryPlanCache(Map properties) { private static QueryInterpretationCache buildQueryPlanCache(Map properties) {
final boolean explicitUseCache = ConfigurationHelper.getBoolean( final boolean explicitUseCache = ConfigurationHelper.getBoolean(
AvailableSettings.QUERY_PLAN_CACHE_ENABLED, AvailableSettings.QUERY_PLAN_CACHE_ENABLED,
properties, properties,
@ -95,15 +98,15 @@ public class QueryEngine {
); );
if ( explicitUseCache || ( explicitMaxPlanCount != null && explicitMaxPlanCount > 0 ) ) { if ( explicitUseCache || ( explicitMaxPlanCount != null && explicitMaxPlanCount > 0 ) ) {
return new QueryPlanCacheStandardImpl( return new QueryInterpretationCacheStandardImpl(
explicitMaxPlanCount != null explicitMaxPlanCount != null
? explicitMaxPlanCount ? explicitMaxPlanCount
: QueryPlanCacheStandardImpl.DEFAULT_QUERY_PLAN_MAX_COUNT : QueryInterpretationCacheStandardImpl.DEFAULT_QUERY_PLAN_MAX_COUNT
); );
} }
else { else {
// disabled // disabled
return QueryPlanCacheDisabledImpl.INSTANCE; return QueryInterpretationCacheDisabledImpl.INSTANCE;
} }
} }
@ -137,8 +140,8 @@ public class QueryEngine {
return semanticQueryProducer; return semanticQueryProducer;
} }
public QueryPlanCache getQueryPlanCache() { public QueryInterpretationCache getInterpretationCache() {
return queryPlanCache; return interpretationCache;
} }
public SqmFunctionRegistry getSqmFunctionRegistry() { public SqmFunctionRegistry getSqmFunctionRegistry() {
@ -158,8 +161,8 @@ public class QueryEngine {
semanticQueryProducer.close(); semanticQueryProducer.close();
} }
if ( queryPlanCache != null ) { if ( interpretationCache != null ) {
queryPlanCache.close(); interpretationCache.close();
} }
if ( sqmFunctionRegistry != null ) { if ( sqmFunctionRegistry != null ) {

View File

@ -25,4 +25,6 @@ public interface QueryImplementor<R> extends Query<R> {
void setOptionalEntityName(String entityName); void setOptionalEntityName(String entityName);
void setOptionalObject(Object optionalObject); void setOptionalObject(Object optionalObject);
QueryParameterBindings getParameterBindings();
} }

View File

@ -18,7 +18,7 @@ import org.hibernate.query.sqm.tree.SqmStatement;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Incubating @Incubating
public interface QueryPlanCache { public interface QueryInterpretationCache {
interface Key { interface Key {
} }

View File

@ -15,6 +15,6 @@ import org.hibernate.metamodel.model.domain.AllowableParameterType;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface QueryParameterBindingTypeResolver { public interface QueryParameterBindingTypeResolver {
AllowableParameterType resolveParameterBindType(Object bindValue); AllowableParameterType<?> resolveParameterBindType(Object bindValue);
AllowableParameterType resolveParameterBindType(Class clazz); AllowableParameterType<?> resolveParameterBindType(Class<?> clazz);
} }

View File

@ -16,4 +16,6 @@ public interface QueryParameterImplementor<T> extends QueryParameter<T> {
void disallowMultiValuedBinding(); void disallowMultiValuedBinding();
void applyAnticipatedType(AllowableParameterType type); void applyAnticipatedType(AllowableParameterType type);
NamedQueryMemento.ParameterMemento toMemento();
} }

View File

@ -31,6 +31,7 @@ import org.hibernate.query.NativeQuery;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.ResultListTransformer; import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer; import org.hibernate.query.TupleTransformer;
import org.hibernate.query.spi.NameableQuery;
import org.hibernate.query.spi.QueryImplementor; import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -38,12 +39,16 @@ import org.hibernate.type.Type;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Incubating @Incubating
public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQuery<R> { public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQuery<R>, NameableQuery {
NativeQueryImplementor setCollectionKey(Serializable key); NativeQueryImplementor setCollectionKey(Serializable key);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// covariant overrides - NativeQuery // covariant overrides - NativeQuery
@Override
NamedNativeQueryMemento toMemento(String name);
@Override @Override
NativeQueryImplementor<R> addScalar(String columnAlias); NativeQueryImplementor<R> addScalar(String columnAlias);

View File

@ -86,7 +86,7 @@ import org.hibernate.sql.ast.produce.metamodel.spi.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.produce.spi.FromClauseAccess; import org.hibernate.sql.ast.produce.spi.FromClauseAccess;
import org.hibernate.sql.ast.produce.spi.FromClauseIndex; import org.hibernate.sql.ast.produce.spi.FromClauseIndex;
import org.hibernate.sql.ast.produce.spi.SqlAliasBaseManager; import org.hibernate.sql.ast.produce.spi.SqlAliasBaseManager;
import org.hibernate.sql.ast.produce.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.query.sqm.tree.expression.function.SqmFunction; import org.hibernate.query.sqm.tree.expression.function.SqmFunction;
import org.hibernate.sql.ast.produce.spi.SqlAstProcessingState; import org.hibernate.sql.ast.produce.spi.SqlAstProcessingState;
import org.hibernate.sql.ast.produce.spi.SqlAstQuerySpecProcessingState; import org.hibernate.sql.ast.produce.spi.SqlAstQuerySpecProcessingState;

View File

@ -0,0 +1,16 @@
/*
* 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.sqm.consume.spi;
/**
* Specialized SemanticQueryWalker (SQM visitor) for producing
* SQL AST
*
* @author Steve Ebersole
*/
public interface SqmToSqlAstConverter<T> extends SemanticQueryWalker<T>, SqlAstCreationState {
}

View File

@ -31,10 +31,10 @@ import org.hibernate.sql.ast.produce.spi.SqlAstSelectDescriptor;
import org.hibernate.sql.ast.produce.sqm.spi.SqmSelectInterpretation; import org.hibernate.sql.ast.produce.sqm.spi.SqmSelectInterpretation;
import org.hibernate.sql.ast.produce.sqm.spi.SqmSelectToSqlAstConverter; import org.hibernate.sql.ast.produce.sqm.spi.SqmSelectToSqlAstConverter;
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl; import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
import org.hibernate.sql.exec.internal.RowTransformerJpaTupleImpl; import org.hibernate.sql.results.internal.RowTransformerJpaTupleImpl;
import org.hibernate.sql.exec.internal.RowTransformerPassThruImpl; import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.exec.internal.RowTransformerSingularReturnImpl; import org.hibernate.sql.results.internal.RowTransformerSingularReturnImpl;
import org.hibernate.sql.exec.internal.RowTransformerTupleTransformerAdapter; import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
import org.hibernate.sql.exec.internal.TupleElementImpl; import org.hibernate.sql.exec.internal.TupleElementImpl;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameter; import org.hibernate.sql.exec.spi.JdbcParameter;

View File

@ -39,7 +39,7 @@ import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.spi.ScrollableResultsImplementor; import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.query.spi.SelectQueryPlan; import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.mutation.spi.DeleteHandler; import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
@ -317,15 +317,15 @@ public class QuerySqmImpl<R>
SelectQueryPlan<R> queryPlan = null; SelectQueryPlan<R> queryPlan = null;
final QueryPlanCache.Key cacheKey = SqmInterpretationsKey.generateFrom( this ); final QueryInterpretationCache.Key cacheKey = SqmInterpretationsKey.generateFrom( this );
if ( cacheKey != null ) { if ( cacheKey != null ) {
queryPlan = getSession().getFactory().getQueryEngine().getQueryPlanCache().getSelectQueryPlan( cacheKey ); queryPlan = getSession().getFactory().getQueryEngine().getInterpretationCache().getSelectQueryPlan( cacheKey );
} }
if ( queryPlan == null ) { if ( queryPlan == null ) {
queryPlan = buildSelectQueryPlan(); queryPlan = buildSelectQueryPlan();
if ( cacheKey != null ) { if ( cacheKey != null ) {
getSession().getFactory().getQueryEngine().getQueryPlanCache().cacheSelectQueryPlan( cacheKey, queryPlan ); getSession().getFactory().getQueryEngine().getInterpretationCache().cacheSelectQueryPlan( cacheKey, queryPlan );
} }
} }
@ -400,15 +400,15 @@ public class QuerySqmImpl<R>
NonSelectQueryPlan queryPlan = null; NonSelectQueryPlan queryPlan = null;
final QueryPlanCache.Key cacheKey = SqmInterpretationsKey.generateNonSelectKey( this ); final QueryInterpretationCache.Key cacheKey = SqmInterpretationsKey.generateNonSelectKey( this );
if ( cacheKey != null ) { if ( cacheKey != null ) {
queryPlan = getSession().getFactory().getQueryEngine().getQueryPlanCache().getNonSelectQueryPlan( cacheKey ); queryPlan = getSession().getFactory().getQueryEngine().getInterpretationCache().getNonSelectQueryPlan( cacheKey );
} }
if ( queryPlan == null ) { if ( queryPlan == null ) {
queryPlan = buildNonSelectQueryPlan(); queryPlan = buildNonSelectQueryPlan();
if ( cacheKey != null ) { if ( cacheKey != null ) {
getSession().getFactory().getQueryEngine().getQueryPlanCache().cacheNonSelectQueryPlan( cacheKey, queryPlan ); getSession().getFactory().getQueryEngine().getInterpretationCache().cacheNonSelectQueryPlan( cacheKey, queryPlan );
} }
} }

View File

@ -13,12 +13,12 @@ import org.hibernate.query.QueryParameter;
import org.hibernate.query.ResultListTransformer; import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer; import org.hibernate.query.TupleTransformer;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryInterpretationCache;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SqmInterpretationsKey implements QueryPlanCache.Key { public class SqmInterpretationsKey implements QueryInterpretationCache.Key {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public static SqmInterpretationsKey generateFrom(QuerySqmImpl query) { public static SqmInterpretationsKey generateFrom(QuerySqmImpl query) {
if ( !isCacheable( query ) ) { if ( !isCacheable( query ) ) {
@ -33,7 +33,7 @@ public class SqmInterpretationsKey implements QueryPlanCache.Key {
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public static QueryPlanCache.Key generateNonSelectKey(QuerySqmImpl query) { public static QueryInterpretationCache.Key generateNonSelectKey(QuerySqmImpl query) {
// todo (6.0) : do we want to cache non-select plans? If so, what requirements? // todo (6.0) : do we want to cache non-select plans? If so, what requirements?
// - very minimum is that it be a "simple" (non-multi-table) statement // - very minimum is that it be a "simple" (non-multi-table) statement
// //

View File

@ -15,7 +15,7 @@ import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor;
import org.hibernate.metamodel.model.relational.spi.Column; import org.hibernate.metamodel.model.relational.spi.Column;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.consume.spi.SqlAppender; import org.hibernate.sql.ast.consume.spi.SqlAppender;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.from.AbstractTableGroup; import org.hibernate.sql.ast.tree.from.AbstractTableGroup;
import org.hibernate.sql.ast.tree.from.TableReferenceJoin; import org.hibernate.sql.ast.tree.from.TableReferenceJoin;

View File

@ -15,7 +15,7 @@ import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor;
import org.hibernate.metamodel.model.relational.spi.Column; import org.hibernate.metamodel.model.relational.spi.Column;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.consume.spi.SqlAppender; import org.hibernate.sql.ast.consume.spi.SqlAppender;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.from.AbstractTableGroup; import org.hibernate.sql.ast.tree.from.AbstractTableGroup;
import org.hibernate.sql.ast.tree.from.TableReferenceJoin; import org.hibernate.sql.ast.tree.from.TableReferenceJoin;

View File

@ -198,7 +198,7 @@ public class SqmFunctionRegistry {
} }
/** /**
* Overlay (put on top) the functions registered here on top of the * Overlay the functions registered here on top of the
* incoming registry, potentially overriding its registrations * incoming registry, potentially overriding its registrations
*/ */
public void overlay(SqmFunctionRegistry registryToOverly) { public void overlay(SqmFunctionRegistry registryToOverly) {

View File

@ -15,7 +15,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.sql.ast.consume.spi.SqlAppender; import org.hibernate.sql.ast.consume.spi.SqlAppender;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
/** /**

View File

@ -15,7 +15,7 @@ import org.hibernate.query.sqm.tree.SqmVisitableNode;
import org.hibernate.sql.SqlExpressableType; import org.hibernate.sql.SqlExpressableType;
import org.hibernate.sql.ast.consume.spi.SelfRenderingExpression; import org.hibernate.sql.ast.consume.spi.SelfRenderingExpression;
import org.hibernate.sql.ast.consume.spi.SqlAppender; import org.hibernate.sql.ast.consume.spi.SqlAppender;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.produce.spi.SqlExpressable; import org.hibernate.sql.ast.produce.spi.SqlExpressable;
import org.hibernate.sql.ast.produce.sqm.spi.SqmExpressionInterpretation; import org.hibernate.sql.ast.produce.sqm.spi.SqmExpressionInterpretation;
import org.hibernate.sql.ast.produce.sqm.spi.SqmToSqlAstConverter; import org.hibernate.sql.ast.produce.sqm.spi.SqmToSqlAstConverter;

View File

@ -15,7 +15,7 @@ import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.consume.spi.SqlAppender; import org.hibernate.sql.ast.consume.spi.SqlAppender;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;

View File

@ -13,7 +13,7 @@ import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.consume.spi.SqlAppender; import org.hibernate.sql.ast.consume.spi.SqlAppender;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import java.util.List; import java.util.List;

View File

@ -15,7 +15,7 @@ import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.consume.spi.SqlAppender; import org.hibernate.sql.ast.consume.spi.SqlAppender;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import java.util.List; import java.util.List;

View File

@ -8,7 +8,7 @@ package org.hibernate.query.sqm.produce.function.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.consume.spi.SqlAppender; import org.hibernate.sql.ast.consume.spi.SqlAppender;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import java.util.List; import java.util.List;

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.tree.expression; package org.hibernate.query.sqm.tree.expression;
import org.hibernate.metamodel.model.domain.AllowableParameterType; import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.ParameterMetadata; import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
@ -110,7 +111,7 @@ public class SqmCriteriaParameter<T>
} }
@Override @Override
public ParameterMemento toMemento() { public NamedCallableQueryMemento.ParameterMemento toMemento() {
throw new UnsupportedOperationException( "ParameterMemento cannot be extracted from Criteria query parameter" ); throw new UnsupportedOperationException( "ParameterMemento cannot be extracted from Criteria query parameter" );
} }
} }

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.sql.ast.produce.spi; package org.hibernate.sql.ast.spi;
import org.hibernate.metamodel.spi.DomainMetamodel; import org.hibernate.metamodel.spi.DomainMetamodel;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.ast.spi;
import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.graph.spi.GraphImplementor;
/**
* @author Steve Ebersole
*/
public interface SqlAstCreationState {
SqlAstCreationContext getCreationContext();
SqlAstProcessingState getCurrentProcessingState();
SqlExpressionResolver getSqlExpressionResolver();
FromClauseAccess getFromClauseAccess();
SqlAliasBaseGenerator getSqlAliasBaseGenerator();
default GraphImplementor getCurrentResultGraphNode() {
throw new NotYetImplementedFor6Exception( getClass() );
}
LockMode determineLockMode(String identificationVariable);
/**
* Visit fetches for the given parent.
*
* We walk fetches via the SqlAstCreationContext because each "context"
* will define differently what should be fetched (HQL versus load)
*/
List<Fetch> visitFetches(FetchParent fetchParent);
}

View File

@ -0,0 +1,21 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.ast.spi;
/**
* Generalized access to state information relative to the "current process" of
* creating a SQL AST.
*
* @author Steve Ebersole
*/
public interface SqlAstProcessingState {
SqlAstProcessingState getParentState();
SqlExpressionResolver getSqlExpressionResolver();
SqlAstCreationState getSqlAstCreationState();
}

View File

@ -0,0 +1,150 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.ast.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.produce.spi.SqlSelectionExpression;
import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
import org.hibernate.sql.ast.tree.expression.CastTarget;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Distinct;
import org.hibernate.sql.ast.tree.expression.ExtractUnit;
import org.hibernate.sql.ast.tree.expression.GenericParameter;
import org.hibernate.sql.ast.tree.expression.NamedParameter;
import org.hibernate.sql.ast.tree.expression.PositionalParameter;
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.sql.ast.tree.expression.Star;
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
import org.hibernate.sql.ast.tree.expression.domain.EntityTypeLiteral;
import org.hibernate.sql.ast.tree.from.FromClause;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
import org.hibernate.sql.ast.tree.predicate.BetweenPredicate;
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
import org.hibernate.sql.ast.tree.predicate.GroupedPredicate;
import org.hibernate.sql.ast.tree.predicate.InListPredicate;
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
import org.hibernate.sql.ast.tree.predicate.Junction;
import org.hibernate.sql.ast.tree.predicate.LikePredicate;
import org.hibernate.sql.ast.tree.predicate.NegatedPredicate;
import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.ast.tree.sort.SortSpecification;
import org.hibernate.sql.ast.tree.update.Assignment;
import org.hibernate.sql.results.spi.SqlSelection;
/**
* @author Steve Ebersole
* @author Andrea Boriero
*/
public interface SqlAstWalker {
SessionFactoryImplementor getSessionFactory();
void visitAssignment(Assignment assignment);
void visitQuerySpec(QuerySpec querySpec);
void visitSortSpecification(SortSpecification sortSpecification);
void visitLimitOffsetClause(QuerySpec querySpec);
void visitSelectClause(SelectClause selectClause);
void visitSqlSelection(SqlSelection sqlSelection);
void visitFromClause(FromClause fromClause);
void visitTableGroup(TableGroup tableGroup);
void visitTableGroupJoin(TableGroupJoin tableGroupJoin);
void visitTableReference(TableReference tableReference);
void visitTableReferenceJoin(TableReferenceJoin tableReferenceJoin);
// void visitEntityExpression(EntityReference entityExpression);
//
// void visitSingularAttributeReference(SingularAttributeReference attributeExpression);
//
// void visitPluralAttribute(PluralAttributeReference pluralAttributeReference);
//
// void visitPluralAttributeElement(PluralAttributeElementReference elementExpression);
//
// void visitPluralAttributeIndex(PluralAttributeIndexReference indexExpression);
void visitColumnReference(ColumnReference columnReference);
void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression);
void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression);
void visitCaseSimpleExpression(CaseSimpleExpression caseSimpleExpression);
void visitNamedParameter(NamedParameter namedParameter);
void visitGenericParameter(GenericParameter parameter);
void visitPositionalParameter(PositionalParameter positionalParameter);
void visitQueryLiteral(QueryLiteral queryLiteral);
void visitUnaryOperationExpression(UnaryOperation unaryOperationExpression);
void visitBetweenPredicate(BetweenPredicate betweenPredicate);
void visitFilterPredicate(FilterPredicate filterPredicate);
void visitGroupedPredicate(GroupedPredicate groupedPredicate);
void visitInListPredicate(InListPredicate inListPredicate);
void visitInSubQueryPredicate(InSubQueryPredicate inSubQueryPredicate);
void visitJunction(Junction junction);
void visitLikePredicate(LikePredicate likePredicate);
void visitNegatedPredicate(NegatedPredicate negatedPredicate);
void visitNullnessPredicate(NullnessPredicate nullnessPredicate);
void visitRelationalPredicate(ComparisonPredicate comparisonPredicate);
void visitSelfRenderingPredicate(SelfRenderingPredicate selfRenderingPredicate);
void visitSelfRenderingExpression(SelfRenderingExpression expression);
void visitSqlSelectionExpression(SqlSelectionExpression expression);
void visitEntityTypeLiteral(EntityTypeLiteral expression);
void visitTuple(SqlTuple tuple);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// functions
void visitExtractUnit(ExtractUnit unit);
void visitCastTarget(CastTarget castTarget);
void visitTrimSpecification(TrimSpecification trimSpecification);
void visitStar(Star star);
void visitDistinct(Distinct distinct);
}

View File

@ -0,0 +1,12 @@
/*
* 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 defining an AST for describing a SQL Statement, as well as
* for creating and consuming then
*/
package org.hibernate.sql.ast.spi;

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.exec.spi;
import java.util.List;
import org.hibernate.sql.results.spi.JdbcValuesMappingDescriptor;
/**
* An anonymous call block (sometimes called an anonymous procedure) to be executed
* on the database. The format of this various by database, but it is essentially an
* unnamed procedure without OUT, INOUT or REF_CURSOR type parameters
*
* @author Steve Ebersole
*/
public interface JdbcAnonBlock extends JdbcOperation {
/**
* Retrieve the "result set mappings" for processing any ResultSets returned from
* the JDBC call. We expose multiple because JPA allows for an application to
* define multiple such mappings which are (unclearly) intended to describe the mapping
* for each ResultSet (in order) returned from the call.
*/
List<JdbcValuesMappingDescriptor> getResultSetMappings();
}

View File

@ -0,0 +1,38 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.exec.spi;
import java.util.List;
/**
* @author Steve Ebersole
*/
public interface JdbcCall extends JdbcAnonBlock {
/**
* If the call is a function, returns the function return descriptor
*/
JdbcCallFunctionReturn getFunctionReturn();
/**
* Get the list of any parameter registrations we need to register
* against the generated CallableStatement
*/
List<JdbcCallParameterRegistration> getParameterRegistrations();
/**
* Extractors for reading back any OUT/INOUT parameters.
*
* @apiNote Note that REF_CURSOR parameters should be handled via
* {@link #getCallRefCursorExtractors()}
*/
List<JdbcCallParameterExtractor> getParameterExtractors();
/**
* Extractors for REF_CURSOR (ResultSet) parameters
*/
List<JdbcCallRefCursorExtractor> getCallRefCursorExtractors();
}

View File

@ -0,0 +1,23 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.exec.spi;
import org.hibernate.sql.results.spi.JdbcValuesMappingDescriptor;
/**
* Executable JDBC command
*
* @author Steve Ebersole
*/
public interface JdbcSelect extends JdbcOperation {
/**
* Retrieve the descriptor for performing the mapping
* of the JDBC ResultSet back to object query results.
*/
JdbcValuesMappingDescriptor getResultSetMapping();
}

View File

@ -0,0 +1,44 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.exec.spi;
import java.util.List;
import java.util.stream.Stream;
import org.hibernate.Incubating;
import org.hibernate.ScrollMode;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.sql.results.spi.RowTransformer;
/**
* An executor for JdbcSelect operations.
*
* @author Steve Ebersole
*/
@Incubating
public interface JdbcSelectExecutor {
// todo (6.0) : Ideally we'd have a singular place (JdbcServices? ServiceRegistry?) to obtain these executors
<R> List<R> list(
JdbcSelect jdbcSelect,
JdbcParameterBindings jdbcParameterBindings,
ExecutionContext executionContext,
RowTransformer<R> rowTransformer);
<R> ScrollableResultsImplementor<R> scroll(
JdbcSelect jdbcSelect,
ScrollMode scrollMode,
JdbcParameterBindings jdbcParameterBindings,
ExecutionContext executionContext,
RowTransformer<R> rowTransformer);
<R> Stream<R> stream(
JdbcSelect jdbcSelect,
JdbcParameterBindings jdbcParameterBindings,
ExecutionContext executionContext,
RowTransformer<R> rowTransformer);
}

View File

@ -0,0 +1,36 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.exec.spi;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* The low-level contract for binding (writing) values to JDBC.
*
* @apiNote At the JDBC-level we always deal with simple/basic values; never
* composites, entities, collections, etc
*
* @author Steve Ebersole
*
* @see JdbcValueExtractor
*/
public interface JdbcValueBinder<J> {
/**
* Bind a value to a prepared statement.
*/
void bind(PreparedStatement statement, int parameterPosition, J value, ExecutionContext executionContext) throws SQLException;
/**
* Bind a value to a CallableStatement.
*
* @apiNote Binding to a CallableStatement by position is done via {@link #bind(PreparedStatement, int, Object, ExecutionContext)} -
* CallableStatement extends PreparedStatement
*/
void bind(CallableStatement statement, String parameterName, J value, ExecutionContext executionContext) throws SQLException;
}

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.exec.spi;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* The low-level contract for extracting (reading) values to JDBC.
*
* @apiNote At the JDBC-level we always deal with simple/basic values; never
* composites, entities, collections, etc
*
* @author Steve Ebersole
*
* @see JdbcValueBinder
* @see SqlExpressableType
*/
public interface JdbcValueExtractor<J> {
/**
* Extract value from result set
*/
J extract(ResultSet resultSet, int jdbcParameterPosition, ExecutionContext executionContext) throws SQLException;
/**
* Extract value from CallableStatement
*/
J extract(
CallableStatement statement,
int jdbcParameterPosition,
ExecutionContext executionContext) throws SQLException;
/**
* Extract value from CallableStatement, by name
*/
J extract(CallableStatement statement, String jdbcParameterName, ExecutionContext executionContext) throws SQLException;
}

View File

@ -12,7 +12,7 @@ import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.sql.JdbcValueExtractor; import org.hibernate.sql.JdbcValueExtractor;
import org.hibernate.sql.ast.consume.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.results.internal.StandardResultSetMapping; import org.hibernate.sql.results.internal.StandardResultSetMapping;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.JdbcValuesMapping; import org.hibernate.sql.results.spi.JdbcValuesMapping;

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.results.internal;
import java.util.List;
import javax.persistence.Tuple;
import javax.persistence.TupleElement;
import org.hibernate.sql.exec.spi.RowTransformer;
/**
* RowTransformer generating a JPA {@link Tuple}
*
* @author Steve Ebersole
*/
public class RowTransformerJpaTupleImpl implements RowTransformer<Tuple> {
private final List<TupleElement<?>> tupleElements;
public RowTransformerJpaTupleImpl(List<TupleElement<?>> tupleElements) {
this.tupleElements = tupleElements;
}
@Override
public Tuple transformRow(Object[] row) {
return new TupleImpl( tupleElements, row );
}
@Override
public int determineNumberOfResultElements(int rawElementCount) {
return 1;
}
}

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.results.internal;
import org.hibernate.Incubating;
import org.hibernate.sql.exec.spi.RowTransformer;
/**
* Essentially a no-op transformer - simply passes the result through
*
* @author Steve Ebersole
*/
@Incubating
public class RowTransformerPassThruImpl<T> implements RowTransformer<T> {
/**
* Singleton access
*/
public static final RowTransformerPassThruImpl INSTANCE = new RowTransformerPassThruImpl();
@SuppressWarnings("unchecked")
public static <T> RowTransformerPassThruImpl<T> instance() {
return INSTANCE;
}
private RowTransformerPassThruImpl() {
}
@Override
@SuppressWarnings("unchecked")
public T transformRow(Object[] row) {
return row.length == 1 ? (T) row[0] : (T) row;
}
}

View File

@ -0,0 +1,36 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.results.internal;
import org.hibernate.sql.exec.spi.RowTransformer;
/**
* @author Steve Ebersole
*/
public class RowTransformerSingularReturnImpl<R> implements RowTransformer<R> {
/**
* Singleton access
*/
public static final RowTransformerSingularReturnImpl INSTANCE = new RowTransformerSingularReturnImpl();
@SuppressWarnings("unchecked")
public static <R> RowTransformerSingularReturnImpl<R> instance() {
return INSTANCE;
}
@Override
@SuppressWarnings("unchecked")
public R transformRow(Object[] row) {
return (R) row[0];
}
@Override
public int determineNumberOfResultElements(int rawElementCount) {
return 1;
}
}

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.results.internal;
import org.hibernate.query.TupleTransformer;
import org.hibernate.sql.results.spi.RowTransformer;
/**
* An adapter for treating a {@link TupleTransformer} as a {@link RowTransformer}
*
* @author Steve Ebersole
*/
public class RowTransformerTupleTransformerAdapter<T> implements RowTransformer<T> {
private final String[] aliases;
private final TupleTransformer<T> tupleTransformer;
public RowTransformerTupleTransformerAdapter(String[] aliases, TupleTransformer<T> tupleTransformer) {
this.aliases = aliases;
this.tupleTransformer = tupleTransformer;
}
@Override
public T transformRow(Object[] row) {
assert aliases == null || row.length == aliases.length;
return tupleTransformer.transformTuple( row, aliases );
}
@Override
public int determineNumberOfResultElements(int rawElementCount) {
return tupleTransformer.determineNumberOfResultElements( rawElementCount );
}
}

View File

@ -9,14 +9,13 @@ package org.hibernate.sql.results.spi;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors;
/** /**
* The "resolved" form of {@link JdbcValuesMappingProducer} providing access * The "resolved" form of {@link JdbcValuesMappingDescriptor} providing access
* to resolved JDBC results ({@link SqlSelection}) descriptors and resolved * to resolved JDBC results ({@link SqlSelection}) descriptors and resolved
* domain results ({@link DomainResult}) descriptors. * domain results ({@link DomainResult}) descriptors.
* *
* @see JdbcValuesMappingProducer#resolve * @see JdbcValuesMappingDescriptor#resolve
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -27,13 +26,9 @@ public interface JdbcValuesMapping {
*/ */
Set<SqlSelection> getSqlSelections(); Set<SqlSelection> getSqlSelections();
List<DomainResult<?>> getDomainResults(); List<DomainResult> getDomainResults();
default List<DomainResultAssembler<?>> resolveAssemblers( List<DomainResultAssembler> resolveAssemblers(
Consumer<Initializer> initializerConsumer, Consumer<Initializer> initializerConsumer,
AssemblerCreationState creationState) { AssemblerCreationState creationState);
return getDomainResults().stream()
.map( domainResult -> domainResult.createResultAssembler( initializerConsumer, creationState ) )
.collect( Collectors.toList() );
}
} }

View File

@ -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.sql.results.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
/**
* Descriptor for the mapping of a JDBC ResultSet providing
* support for delayed resolution if needed (mainly in the
* case of {@link org.hibernate.query.NativeQuery}).
*
* @author Steve Ebersole
*/
public interface JdbcValuesMappingDescriptor {
// todo (6.0) : ? have a specific impl for "consuming" JPA SqlResultSetMapping?
// there are a few different cases for defining result mappings:
// 1) JPA SqlResultSetMapping
// 2) JPA Class-based mapping
// 3) Hibernate's legacy XML-defined mapping
// 4) Hibernate's legacy Query-specific mapping (`NativeQuery#addScalar`, etc).
// 5)
//
// (1), (2) and (3) can really all be handled by the same impl - they are all
// known/resolved up-front. These cases can all be represented as
// `ResultSetMappingDescriptorDefined`
//
// (4) is unique though in that it is not know up
// front and needs to wait until there is a ResultSet available to complete
// its "resolution". This case is represented as `ResultSetMappingDescriptorUndefined`
//
// Both `ResultSetMappingDescriptorDefined` and `ResultSetMappingDescriptorUndefined` could
// definitely use better names
/**
* Access to information about the underlying JDBC values
* such as type, position, column name, etc
*/
interface JdbcValuesMetadata {
/**
* Number of values in the underlying result
*/
int getColumnCount();
/**
* Position of a particular result value by name
*/
int resolveColumnPosition(String columnName);
/**
* Name of a particular result value by position
*/
String resolveColumnName(int position);
/**
* Descriptor of the JDBC/SQL type of a particular result value by
* position
*/
SqlTypeDescriptor resolveSqlTypeDescriptor(int position);
}
/**
* Resolve the selections (both at the JDBC and object level) for this
* mapping. Acts as delayed access to this resolution process to support
* "auto discovery" as needed for "undefined scalar" results as defined by
* JPA.
*
* @param jdbcResultsMetadata Access to information about the underlying results
* @param sessionFactory
* @return The resolved result references
*/
JdbcValuesMapping resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory);
}

View File

@ -10,18 +10,45 @@ import org.hibernate.query.NavigablePath;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
/** /**
* State pertaining to the processing of a single row of a JdbcValuesSource * State pertaining to the processing of a single "row" of a JdbcValuesSource
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface RowProcessingState extends ExecutionContext { public interface RowProcessingState extends ExecutionContext {
/** /**
* Access to the "parent state" related to the overall processing * Access to the state related to the overall processing of the results.
* of the results.
*/ */
JdbcValuesSourceProcessingState getJdbcValuesSourceProcessingState(); JdbcValuesSourceProcessingState getJdbcValuesSourceProcessingState();
/**
* Retrieve the value corresponding to the given SqlSelection as part
* of the "current JDBC row".
*
* @see SqlSelection#getValuesArrayPosition()
* @see #getJdbcValue(int)
*/
default Object getJdbcValue(SqlSelection sqlSelection) {
return getJdbcValue( sqlSelection.getValuesArrayPosition() );
}
/**
* Retrieve the value corresponding to the given index as part
* of the "current JDBC row".
*
* We read all the ResultSet values for the given row one time
* and store them into an array internally based on the principle that multiple
* accesses to this array will be significantly faster than accessing them
* from the ResultSet potentially multiple times.
*/
Object getJdbcValue(int position);
/**
* Callback at the end of processing the current "row"
*/
void finishRowProcessing(); void finishRowProcessing();
/**
* Locate the Initalizer registered for the given path
*/
Initializer resolveInitializer(NavigablePath path); Initializer resolveInitializer(NavigablePath path);
} }

View File

@ -0,0 +1,33 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.results.spi;
import org.hibernate.Incubating;
/**
* Defines transformation of a raw row in the domain query result row.
*
* E.g. a query might select multiple
*
* @see org.hibernate.query.TupleTransformer
*
* @author Steve Ebersole
*/
@Incubating
public interface RowTransformer<T> {
/**
* Transform the "raw" row values into the ultimate query result (for a row)
*/
T transformRow(Object[] row);
/**
* How many result elements will this transformation produce?
*/
default int determineNumberOfResultElements(int rawElementCount) {
return rawElementCount;
}
}

View File

@ -0,0 +1,77 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.results.spi;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.exec.spi.JdbcValueExtractor;
/**
* Represents a selection at the SQL/JDBC level. Essentially made up of:
*
* {@link #getJdbcValueExtractor}:: How to read a value from JDBC (conceptually similar to a method reference)
* {@link #getValuesArrayPosition}:: The position for this selection in relation to the "JDBC values array" (see {@link RowProcessingState#getJdbcValue})
* {@link #getJdbcResultSetIndex()}:: The position for this selection in relation to the JDBC object (ResultSet, etc)
*
* @author Steve Ebersole
*/
public interface SqlSelection extends SqlSelectionGroupNode {
/**
* Get the extractor that can be used to extract JDBC values for this selection
*/
JdbcValueExtractor getJdbcValueExtractor();
// todo (6.0) : add proper support for "virtual" selections
// - things like selecting a literal or a parameter
// - would require the ability to define the "value
// arrays" position and the ResultSet position
// independently on the impls side.
// - would require understanding whether the selection
// occurs in the root query or a subquery. If used
// in a subquery we need to render the parameter rather
// than just manage it locally.
/**
* Get the position within the "JDBC values" array (0-based). Negative indicates this is
* not a "real" selection
*/
int getValuesArrayPosition();
/**
* Get the JDBC position (1-based)
*/
default int getJdbcResultSetIndex() {
return getValuesArrayPosition() + 1;
}
default void prepare(
JdbcValuesMappingDescriptor.JdbcValuesMetadata jdbcResultsMetadata,
SessionFactoryImplementor sessionFactory) {
// By default we have nothing to do. Here as a hook for NativeQuery mapping resolutions
}
@Override
default Object hydrateStateArray(RowProcessingState currentRowState) {
return currentRowState.getJdbcValue( getValuesArrayPosition() );
}
@Override
default void visitSqlSelections(Consumer<SqlSelection> action) {
action.accept( this );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// todo (6.0) : remove methods below
/**
* todo (6.0) : why removing this one?
*/
void accept(SqlAstWalker interpreter);
}

View File

@ -0,0 +1,17 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.results.spi;
import java.util.function.Consumer;
/**
* @author Steve Ebersole
*/
public interface SqlSelectionGroupNode {
Object hydrateStateArray(RowProcessingState currentRowState);
void visitSqlSelections(Consumer<SqlSelection> action);
}

View File

@ -14,7 +14,9 @@ import java.sql.SQLException;
import java.util.Map; import java.util.Map;
import org.hibernate.boot.model.relational.Namespace; import org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;

View File

@ -16,26 +16,19 @@ import java.sql.SQLException;
*/ */
public interface ValueBinder<X> { public interface ValueBinder<X> {
/** /**
* Bind a value to a prepared statement. * Bind a value to a prepared statement by index
* *
* @param st The prepared statement to which to bind the value. * @apiNote Also works for callables since {@link CallableStatement} extends
* @param value The value to bind. * {@link PreparedStatement}
* @param index The position at which to bind the value within the prepared statement
* @param options The options.
* *
* @throws SQLException Indicates a JDBC error occurred. * @throws SQLException Indicates a JDBC error occurred.
*/ */
public void bind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException; void bind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException;
/** /**
* Bind a value to a CallableStatement. * Bind a value to a callable statement by name
*
* @param st The prepared statement to which to bind the value.
* @param value The value to bind.
* @param name The name to bind the value within the prepared statement
* @param options The options.
* *
* @throws SQLException Indicates a JDBC error occurred. * @throws SQLException Indicates a JDBC error occurred.
*/ */
public void bind(CallableStatement st, X value, String name, WrapperOptions options) throws SQLException; void bind(CallableStatement st, X value, String name, WrapperOptions options) throws SQLException;
} }

View File

@ -11,7 +11,8 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
/** /**
* Contract for extracting value via JDBC (from {@link ResultSet} or as output param from {@link CallableStatement}). * Contract for extracting value via JDBC from {@link ResultSet} or as output
* param from {@link CallableStatement}.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -19,17 +20,21 @@ public interface ValueExtractor<X> {
/** /**
* Extract value from result set * Extract value from result set
* *
* @param rs The result set from which to extract the value * @throws SQLException Indicates a JDBC error occurred.
* @param name The name by which to extract the value from the result set */
* @param options The options X extract(ResultSet rs, String name, WrapperOptions options) throws SQLException;
*
* @return The extracted value /**
* Extract value from a callable output parameter by index
* *
* @throws SQLException Indicates a JDBC error occurred. * @throws SQLException Indicates a JDBC error occurred.
*/ */
public X extract(ResultSet rs, String name, WrapperOptions options) throws SQLException; X extract(CallableStatement statement, int index, WrapperOptions options) throws SQLException;
public X extract(CallableStatement statement, int index, WrapperOptions options) throws SQLException; /**
* Extract value from a callable output parameter by name
public X extract(CallableStatement statement, String[] paramNames, WrapperOptions options) throws SQLException; *
* @throws SQLException Indicates a JDBC error occurred.
*/
X extract(CallableStatement statement, String[] paramNames, WrapperOptions options) throws SQLException;
} }

View File

@ -16,8 +16,6 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
/** /**
* Gives binding (nullSafeSet) and extracting (nullSafeGet) code access to options. * Gives binding (nullSafeSet) and extracting (nullSafeGet) code access to options.
* *
* @todo Definitely could use a better name
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface WrapperOptions { public interface WrapperOptions {
@ -26,14 +24,14 @@ public interface WrapperOptions {
* *
* @return {@code true}/{@code false} * @return {@code true}/{@code false}
*/ */
public boolean useStreamForLobBinding(); boolean useStreamForLobBinding();
/** /**
* Obtain access to the {@link LobCreator} * Obtain access to the {@link LobCreator}
* *
* @return The LOB creator * @return The LOB creator
*/ */
public LobCreator getLobCreator(); LobCreator getLobCreator();
/** /**
* Allow remapping of descriptors for dealing with sql type. * Allow remapping of descriptors for dealing with sql type.
@ -42,7 +40,7 @@ public interface WrapperOptions {
* *
* @return The remapped descriptor. May be the same as the known descriptor indicating no remapping. * @return The remapped descriptor. May be the same as the known descriptor indicating no remapping.
*/ */
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor); SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor);
/** /**
* The JDBC {@link TimeZone} used when persisting Timestamp and DateTime properties into the database. * The JDBC {@link TimeZone} used when persisting Timestamp and DateTime properties into the database.
@ -52,5 +50,5 @@ public interface WrapperOptions {
* *
* @return JDBC {@link TimeZone} * @return JDBC {@link TimeZone}
*/ */
public TimeZone getJdbcTimeZone(); TimeZone getJdbcTimeZone();
} }

View File

@ -44,7 +44,7 @@ public class CompositeIdTest extends BaseCoreFunctionalTestCase {
@Test @Test
public void testNonDistinctCountOfEntityWithCompositeId() { public void testNonDistinctCountOfEntityWithCompositeId() {
// the check here is all based on whether we had commas in the expressions inside the count // the check here is all based on whether we had commas in the expressions inside the count
final HQLQueryPlan plan = sessionFactory().getQueryPlanCache().getHQLQueryPlan( final HQLQueryPlan plan = sessionFactory().getQueryInterpretationCache().getHQLQueryPlan(
"select count(o) from Order o", "select count(o) from Order o",
false, false,
Collections.EMPTY_MAP Collections.EMPTY_MAP
@ -70,7 +70,7 @@ public class CompositeIdTest extends BaseCoreFunctionalTestCase {
public void testDistinctCountOfEntityWithCompositeId() { public void testDistinctCountOfEntityWithCompositeId() {
// today we do not account for Dialects supportsTupleDistinctCounts() is false. though really the only // today we do not account for Dialects supportsTupleDistinctCounts() is false. though really the only
// "option" there is to throw an error. // "option" there is to throw an error.
final HQLQueryPlan plan = sessionFactory().getQueryPlanCache().getHQLQueryPlan( final HQLQueryPlan plan = sessionFactory().getQueryInterpretationCache().getHQLQueryPlan(
"select count(distinct o) from Order o", "select count(distinct o) from Order o",
false, false,
Collections.EMPTY_MAP Collections.EMPTY_MAP

View File

@ -157,7 +157,7 @@ public class EntityJoinTest extends BaseNonConfigCoreFunctionalTestCase {
@TestForIssue(jiraKey = "HHH-11538") @TestForIssue(jiraKey = "HHH-11538")
public void testNoImpliedJoinGeneratedForEqualityComparison() { public void testNoImpliedJoinGeneratedForEqualityComparison() {
doInHibernate( this::sessionFactory, session -> { doInHibernate( this::sessionFactory, session -> {
final HQLQueryPlan plan = sessionFactory().getQueryPlanCache().getHQLQueryPlan( final HQLQueryPlan plan = sessionFactory().getQueryInterpretationCache().getHQLQueryPlan(
"select r.id, cust.name " + "select r.id, cust.name " +
"from FinancialRecord r " + "from FinancialRecord r " +
" join Customer cust on r.customer = cust" + " join Customer cust on r.customer = cust" +

View File

@ -14,7 +14,6 @@ import javax.persistence.Id;
import java.util.Collections; import java.util.Collections;
import org.hibernate.Filter; import org.hibernate.Filter;
import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
@ -23,13 +22,10 @@ import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -81,7 +77,7 @@ public class TupleSupportTest extends BaseUnitTestCase {
@Test @Test
public void testImplicitTupleNotEquals() { public void testImplicitTupleNotEquals() {
final String hql = "from TheEntity e where e.compositeValue <> :p1"; final String hql = "from TheEntity e where e.compositeValue <> :p1";
HQLQueryPlan queryPlan = ( (SessionFactoryImplementor) sessionFactory ).getQueryPlanCache() HQLQueryPlan queryPlan = ( (SessionFactoryImplementor) sessionFactory ).getQueryInterpretationCache()
.getHQLQueryPlan( hql, false, Collections.<String,Filter>emptyMap() ); .getHQLQueryPlan( hql, false, Collections.<String,Filter>emptyMap() );
assertEquals( 1, queryPlan.getSqlStrings().length ); assertEquals( 1, queryPlan.getSqlStrings().length );
@ -92,7 +88,7 @@ public class TupleSupportTest extends BaseUnitTestCase {
@Test @Test
public void testImplicitTupleNotInList() { public void testImplicitTupleNotInList() {
final String hql = "from TheEntity e where e.compositeValue not in (:p1,:p2)"; final String hql = "from TheEntity e where e.compositeValue not in (:p1,:p2)";
HQLQueryPlan queryPlan = ( (SessionFactoryImplementor) sessionFactory ).getQueryPlanCache() HQLQueryPlan queryPlan = ( (SessionFactoryImplementor) sessionFactory ).getQueryInterpretationCache()
.getHQLQueryPlan( hql, false, Collections.<String,Filter>emptyMap() ); .getHQLQueryPlan( hql, false, Collections.<String,Filter>emptyMap() );
assertEquals( 1, queryPlan.getSqlStrings().length ); assertEquals( 1, queryPlan.getSqlStrings().length );

View File

@ -52,7 +52,6 @@ import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.OrderColumn; import javax.persistence.OrderColumn;
import org.hibernate.Session;
import org.hibernate.engine.query.spi.HQLQueryPlan; import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.hql.spi.QueryTranslator;
@ -118,7 +117,7 @@ public class MultiInheritanceImplicitDowncastTest extends BaseCoreFunctionalTest
} }
private void testMultiJoinAddition(String hql) { private void testMultiJoinAddition(String hql) {
final HQLQueryPlan plan = sessionFactory().getQueryPlanCache().getHQLQueryPlan( final HQLQueryPlan plan = sessionFactory().getQueryInterpretationCache().getHQLQueryPlan(
hql, hql,
false, false,
Collections.EMPTY_MAP Collections.EMPTY_MAP

View File

@ -11,7 +11,7 @@ import java.util.Map;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.engine.query.spi.HQLQueryPlan; import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
@ -45,7 +45,7 @@ public class GetHqlQueryPlanTest extends BaseCoreFunctionalTestCase {
@Test @Test
public void testHqlQueryPlan() { public void testHqlQueryPlan() {
Session s = openSession(); Session s = openSession();
QueryPlanCache cache = ( ( SessionImplementor ) s ).getFactory().getQueryPlanCache(); QueryInterpretationCache cache = ( ( SessionImplementor ) s ).getFactory().getQueryInterpretationCache();
assertTrue( getEnabledFilters( s ).isEmpty() ); assertTrue( getEnabledFilters( s ).isEmpty() );
HQLQueryPlan plan1 = cache.getHQLQueryPlan( "from Person", false, getEnabledFilters( s ) ); HQLQueryPlan plan1 = cache.getHQLQueryPlan( "from Person", false, getEnabledFilters( s ) );
@ -72,7 +72,7 @@ public class GetHqlQueryPlanTest extends BaseCoreFunctionalTestCase {
@TestForIssue(jiraKey = "HHH-12413") @TestForIssue(jiraKey = "HHH-12413")
public void testExpandingQueryStringMultipleTimesWorks() { public void testExpandingQueryStringMultipleTimesWorks() {
doInHibernate( this::sessionFactory, session -> { doInHibernate( this::sessionFactory, session -> {
QueryPlanCache cache = ( ( SessionImplementor ) session ).getFactory().getQueryPlanCache(); QueryInterpretationCache cache = ( ( SessionImplementor ) session ).getFactory().getQueryInterpretationCache();
String queryString = "from Person where name in :names"; String queryString = "from Person where name in :names";
HQLQueryPlan plan = cache.getHQLQueryPlan( queryString, false, getEnabledFilters( session ) ); HQLQueryPlan plan = cache.getHQLQueryPlan( queryString, false, getEnabledFilters( session ) );
@ -105,7 +105,7 @@ public class GetHqlQueryPlanTest extends BaseCoreFunctionalTestCase {
@Test @Test
public void testHqlQueryPlanWithEnabledFilter() { public void testHqlQueryPlanWithEnabledFilter() {
Session s = openSession(); Session s = openSession();
QueryPlanCache cache = ( (SessionImplementor) s ).getFactory().getQueryPlanCache(); QueryInterpretationCache cache = ( (SessionImplementor) s ).getFactory().getQueryInterpretationCache();
HQLQueryPlan plan1A = cache.getHQLQueryPlan( "from Person", true, getEnabledFilters( s ) ); HQLQueryPlan plan1A = cache.getHQLQueryPlan( "from Person", true, getEnabledFilters( s ) );
HQLQueryPlan plan1B = cache.getHQLQueryPlan( "from Person", false, getEnabledFilters( s ) ); HQLQueryPlan plan1B = cache.getHQLQueryPlan( "from Person", false, getEnabledFilters( s ) );

View File

@ -9,7 +9,7 @@ package org.hibernate.test.queryplan;
import org.junit.Test; import org.junit.Test;
import org.hibernate.engine.query.spi.NativeSQLQueryPlan; import org.hibernate.engine.query.spi.NativeSQLQueryPlan;
import org.hibernate.query.spi.QueryPlanCache; import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn; import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification; import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
@ -29,7 +29,7 @@ public class NativeSQLQueryPlanEqualsTest extends BaseCoreFunctionalTestCase {
@Test @Test
public void testNativeSQLQuerySpecEquals() { public void testNativeSQLQuerySpecEquals() {
QueryPlanCache cache = new QueryPlanCache( sessionFactory() ); QueryInterpretationCache cache = new QueryInterpretationCache( sessionFactory() );
NativeSQLQuerySpecification firstSpec = createSpec(); NativeSQLQuerySpecification firstSpec = createSpec();
NativeSQLQuerySpecification secondSpec = createSpec(); NativeSQLQuerySpecification secondSpec = createSpec();

View File

@ -0,0 +1,18 @@
/*
* 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.testing.envers;
import javax.persistence.EntityManagerFactory;
/**
* Envers contract for something that can build an EntityManagerFactory based on an audit strategy.
*
* @author Chris Cranford
*/
public interface EnversEntityManagerFactoryProducer {
EntityManagerFactory produceEntityManagerFactory(String auditStrategyName);
}

View File

@ -0,0 +1,228 @@
/*
* 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.testing.envers;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.junit5.EntityManagerFactoryAccess;
/**
* @author Chris Cranford
*/
public class EnversEntityManagerFactoryScope implements EntityManagerFactoryAccess {
private final EnversEntityManagerFactoryProducer entityManagerFactoryProducer;
private final Strategy auditStrategy;
private EntityManagerFactory entityManagerFactory;
public EnversEntityManagerFactoryScope(EnversEntityManagerFactoryProducer producer, Strategy auditStrategy) {
this.auditStrategy = auditStrategy;
this.entityManagerFactoryProducer = producer;
}
public void releaseEntityManagerFactory() {
if ( entityManagerFactory != null ) {
entityManagerFactory.close();
entityManagerFactory = null;
}
}
@Override
public EntityManagerFactory getEntityManagerFactory() {
if ( entityManagerFactory == null || !entityManagerFactory.isOpen() ) {
final String strategy = auditStrategy.getSettingValue();
entityManagerFactory = entityManagerFactoryProducer.produceEntityManagerFactory( strategy );
}
return entityManagerFactory;
}
public void inJtaTransaction(Consumer<EntityManager> action) throws Exception {
inJtaTransaction( getEntityManagerFactory(), action );
}
public void inJtaTransaction(EntityManagerFactory factory, Consumer<EntityManager> action) throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager entityManager = factory.createEntityManager();
try {
action.accept( entityManager );
}
finally {
entityManager.close();
TestingJtaPlatformImpl.tryCommit();
}
}
public void inTransaction(Consumer<EntityManager> action) {
inTransaction( getEntityManagerFactory(), action );
}
public void inTransaction(EntityManagerFactory factory, Consumer<EntityManager> action) {
EntityManager entityManager = factory.createEntityManager();
try {
entityManager.getTransaction().begin();
action.accept( entityManager );
entityManager.getTransaction().commit();
}
catch ( Exception e ) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
finally {
entityManager.close();
}
}
public void inTransaction(EntityManager entityManager, Consumer<EntityManager> action) {
try {
entityManager.getTransaction().begin();
action.accept( entityManager );
entityManager.getTransaction().commit();
}
catch ( Exception e ) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
}
@SafeVarargs
public final void inTransactions(Consumer<EntityManager>... actions) {
EntityManager entityManager = getEntityManagerFactory().createEntityManager();
try {
for ( Consumer<EntityManager> action : actions ) {
try {
entityManager.getTransaction().begin();
action.accept( entityManager );
entityManager.getTransaction().commit();
}
catch ( Exception e ) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
}
}
finally {
entityManager.close();
}
}
@SafeVarargs
public final List<Long> inTransactionsWithTimeouts(int timeout, Consumer<EntityManager>... actions) {
EntityManager entityManager = getEntityManagerFactory().createEntityManager();
try {
final List<Long> timestamps = new ArrayList<>();
timestamps.add( System.currentTimeMillis() );
for ( Consumer<EntityManager> action : actions ) {
try {
Thread.sleep( 100 );
entityManager.getTransaction().begin();
action.accept( entityManager );
entityManager.getTransaction().commit();
timestamps.add( System.currentTimeMillis() );
}
catch ( InterruptedException e ) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw new RuntimeException( "Failed to wait on timeout", e );
}
catch ( Exception e ) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
}
return timestamps;
}
finally {
entityManager.close();
}
}
public <R> R inTransaction(Function<EntityManager, R> action) {
return inTransaction( getEntityManagerFactory(), action );
}
public <R> R inTransaction(EntityManagerFactory factory, Function<EntityManager, R> action) {
EntityManager entityManager = factory.createEntityManager();
try {
return inTransaction( entityManager, action );
}
finally {
entityManager.close();
}
}
public <R> R inTransaction(EntityManager entityManager, Function<EntityManager, R> action) {
try {
entityManager.getTransaction().begin();
R result = action.apply( entityManager );
entityManager.getTransaction().commit();
return result;
}
catch ( Exception e ) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
}
public void inJPA(Consumer<EntityManager> action) {
inJPA( getEntityManagerFactory(), action );
}
public <R> R inJPA(Function<EntityManager, R> action) {
return inJPA( getEntityManagerFactory(), action );
}
public void inJPA(EntityManagerFactory factory, Consumer<EntityManager> action) {
EntityManager entityManager = factory.createEntityManager();
try {
action.accept( entityManager );
}
catch ( Exception e ) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
finally {
entityManager.close();
}
}
public <R> R inJPA(EntityManagerFactory factory, Function<EntityManager, R> action) {
EntityManager entityManager = factory.createEntityManager();
try {
return action.apply( entityManager );
}
catch ( Exception e ) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
finally {
entityManager.close();
}
}
}

View File

@ -0,0 +1,18 @@
/*
* 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.testing.envers;
import org.hibernate.SessionFactory;
/**
* Envers contract for something that can build a SessionFactory based on an audit strategy.
*
* @author Chris Cranford
*/
public interface EnversSessionFactoryProducer {
SessionFactory produceSessionFactory(String auditStrategyName);
}

Some files were not shown because too many files have changed in this diff Show More