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.UUID;
import java.util.function.Consumer;
import org.hibernate.SessionFactory;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
@ -113,26 +114,31 @@ public interface Metadata extends Mapping {
/**
* Retrieve named query metadata by name.
*
* @param name The query name
*
* @return The named query metadata, or {@code null}.
*/
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.
*
* @param name The SQL query name.
*
* @return The named query metadata, or {@code null}
*/
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.
@ -143,13 +149,14 @@ public interface Metadata extends Mapping {
*/
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.
*
* @param typeName The name of the type definition to retrieve.
*
* @return The named type definition, or {@code null}
*/
TypeDefinition getTypeDefinition(String typeName);

View File

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

View File

@ -15,6 +15,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
import org.hibernate.HibernateException;
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.SessionFactoryImplementor;
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.FetchProfile;
import org.hibernate.mapping.MappedSuperclass;
@ -85,6 +85,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
private final Map<String, SQLFunction> sqlFunctionMap;
private final Database database;
@SuppressWarnings("WeakerAccess")
public MetadataImpl(
UUID uuid,
MetadataBuildingOptions metadataBuildingOptions,
@ -234,8 +235,8 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
}
@Override
public java.util.Collection<NamedHqlQueryDefinition> getNamedHqlQueryMappings() {
return namedQueryMap.values();
public void visitNamedHqlQueryDefinitions(Consumer<NamedHqlQueryDefinition> definitionConsumer) {
namedQueryMap.values().forEach( definitionConsumer );
}
@Override
@ -244,13 +245,13 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
}
@Override
public java.util.Collection<NamedNativeQueryDefinition> getNamedNativeQueryMappings() {
return namedNativeQueryMap.values();
public void visitNamedNativeQueryDefinitions(Consumer<NamedNativeQueryDefinition> definitionConsumer) {
namedNativeQueryMap.values().forEach( definitionConsumer );
}
@Override
public java.util.Collection<NamedProcedureCallDefinition> getNamedProcedureCallMappings() {
return namedProcedureCallMap.values();
public void visitNamedProcedureCallDefinition(Consumer<NamedProcedureCallDefinition> definitionConsumer) {
namedProcedureCallMap.values().forEach( definitionConsumer );
}
@Override
@ -259,8 +260,8 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
}
@Override
public Map<String, NamedResultSetMappingDefinition> getResultSetMappingDefinitions() {
return sqlResultSetMappingMap;
public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer) {
sqlResultSetMappingMap.values().forEach( definitionConsumer );
}
@Override
@ -318,7 +319,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
}
@Override
public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory) {
public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) {
return new NamedQueryRepositoryImpl(
buildNamedHqlMementos( sessionFactory ),
buildNamedNativeMementos( sessionFactory ),
@ -335,7 +336,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
return map;
}
private Map<String, NamedNativeQueryMemento> buildNamedNativeMementos(SessionFactoryImpl sessionFactory) {
private Map<String, NamedNativeQueryMemento> buildNamedNativeMementos(SessionFactoryImplementor sessionFactory) {
final HashMap<String, NamedNativeQueryMemento> map = new HashMap<>();
if ( namedNativeQueryMap != null ) {
namedNativeQueryMap.forEach( (key, value) -> map.put( key, value.resolve( sessionFactory ) ) );
@ -351,7 +352,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
return map;
}
private Map<String, NamedResultSetMappingMemento> buildResultSetMappingMementos(SessionFactoryImpl sessionFactory) {
private Map<String, NamedResultSetMappingMemento> buildResultSetMappingMementos(SessionFactoryImplementor sessionFactory) {
final HashMap<String, NamedResultSetMappingMemento> map = new HashMap<>();
if ( sqlResultSetMappingMap != null ) {
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.Set;
import java.util.UUID;
import java.util.function.Consumer;
import org.hibernate.MappingException;
import org.hibernate.SessionFactory;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.internal.NamedProcedureCallDefinitionImpl;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.mapping.FetchProfile;
@ -118,13 +116,13 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
}
@Override
public NamedHqlQueryMementoImpl getNamedHqlQueryMapping(String name) {
public NamedHqlQueryDefinition getNamedHqlQueryMapping(String name) {
return delegate.getNamedHqlQueryMapping( name );
}
@Override
public Collection<NamedHqlQueryMementoImpl> getNamedHqlQueryMappings() {
return delegate.getNamedHqlQueryMappings();
public void visitNamedHqlQueryDefinitions(Consumer<NamedHqlQueryDefinition> definitionConsumer) {
delegate.visitNamedHqlQueryDefinitions( definitionConsumer );
}
@Override
@ -133,23 +131,23 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
}
@Override
public Collection<NamedNativeQueryDefinition> getNamedNativeQueryMappings() {
return delegate.getNamedNativeQueryMappings();
public void visitNamedNativeQueryDefinitions(Consumer<NamedNativeQueryDefinition> definitionConsumer) {
delegate.visitNamedNativeQueryDefinitions( definitionConsumer );
}
@Override
public Collection<NamedProcedureCallDefinitionImpl> getNamedProcedureCallMappings() {
return delegate.getNamedProcedureCallMappings();
public void visitNamedProcedureCallDefinition(Consumer<NamedProcedureCallDefinition> definitionConsumer) {
delegate.visitNamedProcedureCallDefinition( definitionConsumer );
}
@Override
public ResultSetMappingDescriptor getResultSetMapping(String name) {
public NamedResultSetMappingDefinition getResultSetMapping(String name) {
return delegate.getResultSetMapping( name );
}
@Override
public Map<String, ResultSetMappingDescriptor> getResultSetMappingDefinitions() {
return delegate.getResultSetMappingDefinitions();
public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer) {
delegate.visitNamedResultSetMappingDefinition( definitionConsumer );
}
@Override
@ -224,11 +222,6 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
return delegate.getTypeResolver();
}
@Override
public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory) {
return delegate.buildNamedQueryRepository( sessionFactory );
}
@Override
public void validate() throws MappingException {
delegate.validate();

View File

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

View File

@ -33,6 +33,7 @@ import org.hibernate.loader.BatchFetchStyle;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
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.StatementInspector;
import org.hibernate.stat.Statistics;
@ -315,5 +316,8 @@ public interface SessionFactoryOptions {
return false;
}
SqmFunctionRegistry getSqmFunctionRegistry();
boolean isOmitJoinOfSuperclassTablesEnabled();
}

View File

@ -18,7 +18,7 @@ import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
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.transaction.spi.TransactionCoordinator;
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";
/**
* 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
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
@ -1239,13 +1239,13 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
* <li>{@link org.hibernate.engine.query.spi.NativeSQLQueryPlan}</li>
* </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";
/**
* 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";

View File

@ -97,6 +97,8 @@ import org.hibernate.mapping.Table;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
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.sql.ANSICaseFragment;
import org.hibernate.sql.ANSIJoinFragment;
@ -261,6 +263,10 @@ public abstract class Dialect implements ConversionContext {
uniqueDelegate = new DefaultUniqueDelegate( this );
}
public void initializeFunctionRegistry(QueryEngine queryEngine) {
}
/**
* Get an instance of the dialect specified by the current <tt>System</tt> properties.
* @deprecated this static method will be removed.
@ -2737,6 +2743,20 @@ public abstract class Dialect implements ConversionContext {
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
* 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.Query;
import javax.persistence.SynchronizationType;
import javax.persistence.criteria.CriteriaBuilder;
import org.hibernate.CustomEntityDirtinessStrategy;
import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.MappingException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
@ -36,27 +34,28 @@ import org.hibernate.cfg.Settings;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.dialect.Dialect;
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.SqlExceptionHelper;
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.graph.spi.RootGraphImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.metadata.ClassMetadata;
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.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
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.stat.spi.StatisticsImplementor;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
/**
* Base delegating implementation of the SessionFactory and SessionFactoryImplementor
@ -208,6 +207,11 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getTypeResolver();
}
@Override
public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
return delegate.getIdentifierGenerator( rootEntityName );
}
@Override
public Map<String, Object> getProperties() {
return delegate.getProperties();
@ -243,26 +247,6 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
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
public String[] getImplementors(String className) throws MappingException {
return delegate.getImplementors( className );
@ -283,36 +267,6 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
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
public SQLExceptionConverter getSQLExceptionConverter() {
return delegate.getSQLExceptionConverter();
@ -353,11 +307,21 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getFetchProfile( name );
}
@Override
public JpaMetamodel getJpaMetamodel() {
return delegate.getJpaMetamodel();
}
@Override
public ServiceRegistryImplementor getServiceRegistry() {
return delegate.getServiceRegistry();
}
@Override
public Integer getMaximumFetchDepth() {
return delegate.getMaximumFetchDepth();
}
@Override
public void addObserver(SessionFactoryObserver observer) {
delegate.addObserver( observer );
@ -373,11 +337,6 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getCurrentTenantIdentifierResolver();
}
@Override
public NamedQueryRepository getNamedQueryRepository() {
return delegate.getNamedQueryRepository();
}
@Override
public Iterable<EntityNameResolver> iterateEntityNameResolvers() {
return delegate.iterateEntityNameResolvers();
@ -428,6 +387,16 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getName();
}
@Override
public TypeConfiguration getTypeConfiguration() {
return delegate.getTypeConfiguration();
}
@Override
public QueryEngine getQueryEngine() {
return delegate.getQueryEngine();
}
@Override
public Reference getReference() throws NamingException {
return delegate.getReference();
@ -459,7 +428,7 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
}
@Override
public CriteriaBuilder getCriteriaBuilder() {
public NodeBuilder getCriteriaBuilder() {
return delegate.getCriteriaBuilder();
}
@ -474,12 +443,12 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
}
@Override
public Type resolveParameterBindType(Object bindValue) {
public AllowableParameterType<?> resolveParameterBindType(Object bindValue) {
return delegate.resolveParameterBindType( bindValue );
}
@Override
public Type resolveParameterBindType(Class clazz) {
public AllowableParameterType<?> resolveParameterBindType(Class<?> clazz) {
return delegate.resolveParameterBindType( clazz );
}
}

View File

@ -15,13 +15,11 @@ import javax.persistence.EntityGraph;
import org.hibernate.CustomEntityDirtinessStrategy;
import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.MappingException;
import org.hibernate.Metamodel;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.spi.CacheImplementor;
import org.hibernate.cfg.Settings;
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.entity.EntityPersister;
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.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.produce.spi.SqmCreationContext;
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.type.Type;
import org.hibernate.type.TypeResolver;
@ -117,38 +109,6 @@ public interface SessionFactoryImplementor
*/
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.
*
@ -212,28 +172,6 @@ public interface SessionFactoryImplementor
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 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}).
*/
@ -242,51 +180,6 @@ public interface SessionFactoryImplementor
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.
*

View File

@ -606,11 +606,11 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
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 {
return getFactory().getQueryPlanCache().getNativeSQLQueryPlan( spec );
return getFactory().getQueryInterpretationCache().getNativeSQLQueryPlan( spec );
}
@Override
@ -640,7 +640,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
private NativeQueryImplementor createNativeQuery(NamedNativeQueryMemento queryDefinition, boolean isOrdinalParameterZeroBased) {
final ParameterMetadata parameterMetadata = factory.getQueryPlanCache().getSQLParameterMetadata(
final ParameterMetadata parameterMetadata = factory.getQueryInterpretationCache().getSQLParameterMetadata(
queryDefinition.getQueryString(),
isOrdinalParameterZeroBased
);
@ -733,7 +733,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
@SuppressWarnings({"unchecked", "WeakerAccess", "StatementWithEmptyBody"})
protected void resultClassChecking(Class resultClass, Query hqlQuery) {
// make sure the query is a select -> HHH-7192
final HQLQueryPlan queryPlan = getFactory().getQueryPlanCache().getHQLQueryPlan(
final HQLQueryPlan queryPlan = getFactory().getQueryInterpretationCache().getHQLQueryPlan(
hqlQuery.getQueryString(),
false,
getLoadQueryInfluencers().getEnabledFilters()
@ -829,7 +829,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
final NativeQueryImpl query = new NativeQueryImpl(
queryDefinition,
this,
factory.getQueryPlanCache().getSQLParameterMetadata( queryDefinition.getQueryString(), false )
factory.getQueryInterpretationCache().getSQLParameterMetadata( queryDefinition.getQueryString(), false )
);
if ( Tuple.class.equals( resultType ) ) {
query.setResultTransformer( new NativeQueryTupleTransformer() );
@ -982,7 +982,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
queryString,
false,
this,
getFactory().getQueryPlanCache().getSQLParameterMetadata( queryString, isOrdinalParameterZeroBased )
getFactory().getQueryInterpretationCache().getSQLParameterMetadata( queryString, isOrdinalParameterZeroBased )
);
query.setComment( "dynamic native SQL 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.Fetch;
import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.query.spi.ReturnMetadata;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.SessionBuilderImplementor;
import org.hibernate.engine.spi.SessionEventListenerManager;
@ -97,15 +96,18 @@ import org.hibernate.jpa.internal.PersistenceUnitUtilImpl;
import org.hibernate.mapping.RootClass;
import org.hibernate.metadata.ClassMetadata;
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.persister.entity.EntityPersister;
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.HibernateProxyHelper;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.spi.QueryPlanCache;
import org.hibernate.query.hql.spi.HqlQueryImplementor;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.sql.spi.NativeQueryImplementor;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
import org.hibernate.query.NativeQuery;
@ -125,9 +127,9 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tool.schema.spi.DelayedDropAction;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
import org.hibernate.type.SerializableType;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger;
@ -180,8 +182,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
private final transient NodeBuilder criteriaBuilder;
private final PersistenceUnitUtil jpaPersistenceUnitUtil;
private final transient CacheImplementor cacheAccess;
private final transient NamedQueryRepository namedQueryRepository;
private final transient QueryPlanCache queryPlanCache;
private final transient QueryEngine queryEngine;
private final transient CurrentSessionContext currentSessionContext;
@ -213,6 +214,8 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
prepareEventListeners( metadata );
this.queryEngine = QueryEngine.from( this, metadata );
final CfgXmlAccessService cfgXmlAccessService = serviceRegistry.getService( CfgXmlAccessService.class );
String sfName = settings.getSessionFactoryName();
@ -244,7 +247,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
this.sqlFunctionRegistry = new SQLFunctionRegistry( jdbcServices.getJdbcEnvironment().getDialect(), options.getCustomSqlFunctionMap() );
this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class );
this.criteriaBuilder = new SqmCriteriaNodeBuilder.create( this );
this.criteriaBuilder = SqmCriteriaNodeBuilder.create( this );
this.jpaPersistenceUnitUtil = new PersistenceUnitUtilImpl( this );
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( "Instantiating session factory with properties: %s", properties );
this.queryPlanCache = new QueryPlanCache( this );
class IntegratorObserver implements SessionFactoryObserver {
private ArrayList<Integrator> integrators = new ArrayList<>();
@ -301,9 +302,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
this.metamodel = (MetamodelImplementor) metadata.getTypeConfiguration().scope( this )
.create( metadata, determineJpaMetaModelPopulationSetting( properties ) );
//Named Queries:
this.namedQueryRepository = metadata.buildNamedQueryRepository( this );
settings.getMultiTableBulkIdStrategy().prepare(
jdbcServices,
buildLocalConnectionAccess(),
@ -320,26 +318,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
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.fetchProfiles = new HashMap<>();
for ( org.hibernate.mapping.FetchProfile mappingProfile : metadata.getFetchProfiles() ) {
@ -408,7 +386,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
eventListenerRegistry.prepare( metadata );
for ( Map.Entry entry : ( (Map<?, ?>) cfgService.getSettings() ).entrySet() ) {
if ( !String.class.isInstance( entry.getKey() ) ) {
if ( !(entry.getKey() instanceof String) ) {
continue;
}
final String propertyName = (String) entry.getKey();
@ -421,6 +399,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
final EventType eventType = EventType.resolveEventTypeByName( eventTypeName );
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
for ( String listenerImpl : LISTENER_SEPARATION_PATTERN.split( ( (String) entry.getValue() ) ) ) {
//noinspection unchecked
eventListenerGroup.appendListener( instantiate( listenerImpl, classLoaderService ) );
}
}
@ -534,6 +513,16 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
return name;
}
@Override
public TypeConfiguration getTypeConfiguration() {
return getMetamodel().getTypeConfiguration();
}
@Override
public QueryEngine getQueryEngine() {
return null;
}
@Override
public JdbcServices getJdbcServices() {
return jdbcServices;
@ -555,25 +544,12 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
return metamodel.getTypeConfiguration().getTypeResolver();
}
public QueryPlanCache getQueryPlanCache() {
return queryPlanCache;
}
private Map<String,HibernateException> checkNamedQueries() throws HibernateException {
return namedQueryRepository.checkNamedQueries( queryPlanCache );
}
@Override
public DeserializationResolver getDeserializationResolver() {
return new DeserializationResolver() {
@Override
public SessionFactoryImplementor resolve() {
return (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.findSessionFactory(
uuid,
name
);
}
};
return (DeserializationResolver) () -> (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.findSessionFactory(
uuid,
name
);
}
@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 {
return getMetamodel().entityPersister( className ).getIdentifierType();
}
@ -715,18 +685,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
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 {
return getClassMetadata( persistentClass.getName() );
}
@ -800,9 +758,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
metamodel.close();
}
if ( queryPlanCache != null ) {
queryPlanCache.cleanup();
}
queryEngine.close();
if ( delayedDropAction != null ) {
delayedDropAction.perform( serviceRegistry );
@ -839,31 +795,34 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
// first, handle StoredProcedureQuery
try {
final ProcedureCall unwrapped = query.unwrap( ProcedureCall.class );
final ProcedureCallImplementor unwrapped = query.unwrap( ProcedureCallImplementor.class );
if ( unwrapped != null ) {
addNamedStoredProcedureQuery( name, unwrapped );
getQueryEngine().getNamedQueryRepository().registerCallableQueryMemento(
name,
unwrapped.toMemento( name )
);
return;
}
}
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
try {
org.hibernate.query.Query hibernateQuery = query.unwrap( org.hibernate.query.Query.class );
QueryImplementor<?> hibernateQuery = query.unwrap( QueryImplementor.class );
if ( hibernateQuery != null ) {
// create and register the proper NamedQueryDefinition...
if ( NativeQuery.class.isInstance( hibernateQuery ) ) {
getNamedQueryRepository().registerNamedSQLQueryDefinition(
if ( hibernateQuery instanceof NativeQueryImplementor ) {
getQueryEngine().getNamedQueryRepository().registerNativeQueryMemento(
name,
extractSqlQueryDefinition( (NativeQuery) hibernateQuery, name )
( (NativeQueryImplementor) hibernateQuery ).toMemento( name )
);
}
else {
getNamedQueryRepository().registerNamedQueryDefinition(
getQueryEngine().getNamedQueryRepository().registerHqlQueryMemento(
name,
extractHqlQueryDefinition( hibernateQuery, name )
( ( HqlQueryImplementor ) hibernateQuery ).toMemento( name )
);
}
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
public <T> T unwrap(Class<T> type) {
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
public ServiceRegistryImplementor getServiceRegistry() {
return serviceRegistry;
@ -1061,7 +980,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
}
@Override
public Type resolveParameterBindType(Object bindValue) {
public AllowableParameterType<?> resolveParameterBindType(Object bindValue) {
if ( bindValue == null ) {
// we can't guess
return null;
@ -1071,27 +990,8 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
}
@Override
public Type resolveParameterBindType(Class clazz){
String typename = clazz.getName();
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 AllowableParameterType<?> resolveParameterBindType(Class<?> javaType) {
return getMetamodel().resolveQueryParameterType( javaType );
}
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
*/
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,
*/
private final ConcurrentHashMap<String, String> nameUuidXref = new ConcurrentHashMap<String, String>();
private final ConcurrentHashMap<String, String> nameUuidXref = new ConcurrentHashMap<>();
private SessionFactoryRegistry() {
LOG.debugf( "Initializing SessionFactoryRegistry : %s", this );
@ -65,7 +65,7 @@ public class SessionFactoryRegistry {
String uuid,
String name,
boolean isNameAlsoJndiName,
SessionFactory instance,
SessionFactoryImplementor instance,
JndiService jndiService) {
if ( uuid == null ) {
throw new IllegalArgumentException( "SessionFactory UUID cannot be null" );
@ -143,16 +143,16 @@ public class SessionFactoryRegistry {
*
* @return The SessionFactory
*/
public SessionFactory getNamedSessionFactory(String name) {
public SessionFactoryImplementor getNamedSessionFactory(String name) {
LOG.debugf( "Lookup: name=%s", name );
final String uuid = nameUuidXref.get( name );
// protect against NPE -- see HHH-8428
return uuid == null ? null : getSessionFactory( uuid );
}
public SessionFactory getSessionFactory(String uuid) {
public SessionFactoryImplementor getSessionFactory(String uuid) {
LOG.debugf( "Lookup: uid=%s", uuid );
final SessionFactory sessionFactory = sessionFactoryMap.get( uuid );
final SessionFactoryImplementor sessionFactory = sessionFactoryMap.get( uuid );
if ( sessionFactory == null && LOG.isDebugEnabled() ) {
LOG.debugf( "Not found: %s", uuid );
LOG.debug( sessionFactoryMap.toString() );
@ -160,8 +160,8 @@ public class SessionFactoryRegistry {
return sessionFactory;
}
public SessionFactory findSessionFactory(String uuid, String name) {
SessionFactory sessionFactory = getSessionFactory( uuid );
public SessionFactoryImplementor findSessionFactory(String uuid, String name) {
SessionFactoryImplementor sessionFactory = getSessionFactory( uuid );
if ( sessionFactory == null && StringHelper.isNotEmpty( name ) ) {
sessionFactory = getNamedSessionFactory( name );
}
@ -205,10 +205,13 @@ public class SessionFactoryRegistry {
LOG.factoryUnboundFromName( jndiName );
final String uuid = nameUuidXref.remove( jndiName );
//noinspection StatementWithEmptyBody
if ( uuid == null ) {
// serious problem... but not sure what to do yet
}
sessionFactoryMap.remove( uuid );
else {
sessionFactoryMap.remove( uuid );
}
}
@Override

View File

@ -1691,7 +1691,7 @@ public final class SessionImpl
if ( roleAfterFlush == null ) {
throw new QueryException( "The collection was unreferenced" );
}
plan = factory.getQueryPlanCache().getFilterQueryPlan(
plan = factory.getQueryInterpretationCache().getFilterQueryPlan(
filter,
roleAfterFlush.getRole(),
shallow,
@ -1701,7 +1701,7 @@ public final class SessionImpl
else {
// otherwise, we only need to flush if there are in-memory changes
// to the queried tables
plan = factory.getQueryPlanCache().getFilterQueryPlan(
plan = factory.getQueryInterpretationCache().getFilterQueryPlan(
filter,
roleBeforeFlush.getRole(),
shallow,
@ -1716,7 +1716,7 @@ public final class SessionImpl
if ( roleAfterFlush == null ) {
throw new QueryException( "The collection was dereferenced" );
}
plan = factory.getQueryPlanCache().getFilterQueryPlan(
plan = factory.getQueryInterpretationCache().getFilterQueryPlan(
filter,
roleAfterFlush.getRole(),
shallow,
@ -2106,7 +2106,7 @@ public final class SessionImpl
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() );
@ -2130,7 +2130,7 @@ public final class SessionImpl
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() );

View File

@ -34,6 +34,8 @@ public interface AllowableOutputParameterType<J> extends AllowableParameterType<
*/
SqlTypeDescriptor getSqlTypeDescriptor();
/**
* 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.AllowableParameterType;
import org.hibernate.procedure.spi.FunctionReturnImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.ProcedureCallImplementor;
import org.hibernate.query.QueryParameter;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
@ -108,17 +108,13 @@ public class FunctionReturnImpl implements FunctionReturnImplementor {
}
@Override
public ParameterMemento toMemento() {
// todo (6.0) : do we need a FunctionReturnMemento?
return new ParameterMemento() {
@Override
public QueryParameter toQueryParameter(SharedSessionContractImplementor session) {
if ( ormType != null ) {
return new FunctionReturnImpl( procedureCall, ormType );
}
else {
return new FunctionReturnImpl( procedureCall, jdbcTypeCode );
}
public NamedCallableQueryMemento.ParameterMemento toMemento() {
return session -> {
if ( ormType != null ) {
return new FunctionReturnImpl( procedureCall, ormType );
}
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.spi.NamedCallableQueryMemento;
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.NamedQueryMemento;
@ -32,7 +32,7 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
private final String callableName;
private final ParameterStrategy parameterStrategy;
private final List<ParameterMemento> parameterMementos;
private final List<NamedCallableQueryMemento.ParameterMemento> parameterMementos;
private final String[] resultSetMappingNames;
private final Class[] resultSetMappingClasses;
@ -47,7 +47,7 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
String name,
String callableName,
ParameterStrategy parameterStrategy,
List<ParameterMemento> parameterMementos,
List<NamedCallableQueryMemento.ParameterMemento> parameterMementos,
String[] resultSetMappingNames,
Class[] resultSetMappingClasses,
Set<String> querySpaces,
@ -86,7 +86,7 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
}
@Override
public List<ParameterMemento> getParameterMementos() {
public List<NamedCallableQueryMemento.ParameterMemento> getParameterMementos() {
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.
*/
public static class ParameterMementoImpl implements ParameterMemento {
public static class ParameterMementoImpl implements NamedCallableQueryMemento.ParameterMemento {
private final Integer position;
private final String name;
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.ParameterStrategy;
import org.hibernate.procedure.spi.ProcedureCallImplementor;
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.Query;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.internal.QueryOptionsImpl;
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.MutableQueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
@ -108,8 +105,8 @@ public class ProcedureCallImpl<R>
super( session );
this.procedureName = procedureName;
this.parameterMetadata = new ProcedureParameterMetadataImpl( this );
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this );
this.parameterMetadata = new ProcedureParameterMetadataImpl();
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.synchronizedQuerySpaces = null;
this.domainResultProducers = null;
@ -128,8 +125,8 @@ public class ProcedureCallImpl<R>
this.procedureName = procedureName;
this.parameterMetadata = new ProcedureParameterMetadataImpl( this );
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this );
this.parameterMetadata = new ProcedureParameterMetadataImpl();
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.domainResultProducers = CollectionHelper.arrayList( resultClasses.length );
this.synchronizedQuerySpaces = new HashSet<>();
@ -159,8 +156,8 @@ public class ProcedureCallImpl<R>
this.procedureName = procedureName;
this.parameterMetadata = new ProcedureParameterMetadataImpl( this );
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this );
this.parameterMetadata = new ProcedureParameterMetadataImpl();
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.domainResultProducers = CollectionHelper.arrayList( resultSetMappingNames.length );
this.synchronizedQuerySpaces = new HashSet<>();
@ -183,8 +180,8 @@ public class ProcedureCallImpl<R>
super( session );
this.procedureName = memento.getCallableName();
this.parameterMetadata = new ProcedureParameterMetadataImpl( this, memento );
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this );
this.parameterMetadata = new ProcedureParameterMetadataImpl( memento, session );
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.domainResultProducers = new ArrayList<>();
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
@ -240,6 +237,11 @@ public class ProcedureCallImpl<R>
return this;
}
@Override
public QueryParameterBindings getParameterBindings() {
return paramBindings;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DomainParameterBindingContext
@ -299,13 +301,11 @@ public class ProcedureCallImpl<R>
@SuppressWarnings("unchecked")
public <T> ProcedureParameter<T> registerParameter(int position, Class<T> javaType, ParameterMode mode) {
final ProcedureParameterImpl procedureParameter = new ProcedureParameterImpl(
this,
position,
mode,
javaType,
getSession().getFactory().getMetamodel().resolveQueryParameterType( javaType )
getSessionFactory().getDomainModel().resolveQueryParameterType( javaType )
);
registerParameter( procedureParameter );
return procedureParameter;
}
@ -328,13 +328,12 @@ public class ProcedureCallImpl<R>
@Override
@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(
this,
name,
mode,
type,
getSession().getFactory().getMetamodel().resolveQueryParameterType( type )
javaType,
getSessionFactory().getDomainModel().resolveQueryParameterType( javaType )
);
registerParameter( parameter );
@ -408,7 +407,7 @@ public class ProcedureCallImpl<R>
public void accept(QueryParameter queryParameter) {
try {
final ProcedureParameterImplementor registration = (ProcedureParameterImplementor) queryParameter;
registration.prepare( statement, i );
registration.prepare( statement, i, ProcedureCallImpl.this );
if ( registration.getMode() == ParameterMode.REF_CURSOR ) {
i++;
}
@ -525,14 +524,14 @@ public class ProcedureCallImpl<R>
);
}
private static List<NamedCallableQueryMementoImpl.ParameterMemento> toParameterMementos(
private static List<NamedCallableQueryMemento.ParameterMemento> toParameterMementos(
ProcedureParameterMetadataImpl parameterMetadata) {
if ( parameterMetadata.getParameterStrategy() == ParameterStrategy.UNKNOWN ) {
// none...
return Collections.emptyList();
}
final List<NamedCallableQueryMementoImpl.ParameterMemento> mementos = new ArrayList<>();
final List<NamedCallableQueryMemento.ParameterMemento> mementos = new ArrayList<>();
parameterMetadata.visitRegistrations(
queryParameter -> {
@ -922,5 +921,4 @@ public class ProcedureCallImpl<R>
public ProcedureCallImplementor<R> setParameter(int position, Date value, TemporalType 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.ResultSet;
import java.util.List;
import java.util.function.Supplier;
import java.sql.SQLException;
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.spi.ParameterRegistrationImplementor;
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.result.Output;
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.
@ -27,7 +30,7 @@ public class ProcedureOutputsImpl extends OutputsImpl implements ProcedureOutput
private final ProcedureCallImpl procedureCall;
private final CallableStatement callableStatement;
private final ParameterRegistrationImplementor[] refCursorParameters;
private final ProcedureParameterImplementor[] refCursorParameters;
private int refCursorParamIndex;
ProcedureOutputsImpl(ProcedureCallImpl procedureCall, CallableStatement callableStatement) {
@ -39,18 +42,34 @@ public class ProcedureOutputsImpl extends OutputsImpl implements ProcedureOutput
}
@Override
public <T> T getOutputParameterValue(ParameterRegistration<T> parameterRegistration) {
return ( (ParameterRegistrationImplementor<T>) parameterRegistration ).extract( callableStatement );
public <T> T getOutputParameterValue(ProcedureParameter<T> parameter) {
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
public Object getOutputParameterValue(String name) {
return procedureCall.getParameterRegistration( name ).extract( callableStatement );
return getOutputParameterValue( procedureCall.getParameterMetadata().getQueryParameter( name ) );
}
@Override
public Object getOutputParameterValue(int position) {
return procedureCall.getParameterRegistration( position ).extract( callableStatement );
return getOutputParameterValue( procedureCall.getParameterMetadata().getQueryParameter( position ) );
}
@Override
@ -80,7 +99,7 @@ public class ProcedureOutputsImpl extends OutputsImpl implements ProcedureOutput
@Override
protected Output buildExtendedReturn() {
ProcedureOutputsImpl.this.refCursorParamIndex++;
final ParameterRegistrationImplementor refCursorParam = ProcedureOutputsImpl.this.refCursorParameters[refCursorParamIndex];
final ProcedureParameterImplementor refCursorParam = ProcedureOutputsImpl.this.refCursorParameters[refCursorParamIndex];
ResultSet resultSet;
if ( refCursorParam.getName() != null ) {
resultSet = ProcedureOutputsImpl.this.procedureCall.getSession().getFactory().getServiceRegistry()

View File

@ -1,20 +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>.
* 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;
package org.hibernate.procedure.internal;
import java.util.HashMap;
import java.util.Map;
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.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.QueryParameterBindingTypeResolver;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor;
@ -23,23 +24,25 @@ import org.hibernate.query.spi.QueryParameterImplementor;
*/
public class ProcedureParamBindings implements QueryParameterBindings {
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(
ProcedureParameterMetadataImpl parameterMetadata,
ProcedureCallImpl procedureCall) {
QueryParameterBindingTypeResolver typeResolver) {
this.parameterMetadata = parameterMetadata;
this.procedureCall = procedureCall;
this.typeResolver = typeResolver;
}
public ProcedureParameterMetadataImpl getParameterMetadata() {
return parameterMetadata;
}
public ProcedureCallImpl getProcedureCall() {
return procedureCall;
@Override
public boolean isBound(QueryParameterImplementor<?> parameter) {
//noinspection SuspiciousMethodCalls
return bindingMap.containsKey( parameter );
}
@Override
@ -47,16 +50,17 @@ public class ProcedureParamBindings implements QueryParameterBindings {
return getBinding( parameterMetadata.resolve( parameter ) );
}
public QueryParameterBinding<?> getBinding(ProcedureParameterImplementor parameter) {
public ProcedureParameterBindingImplementor<?> getBinding(ProcedureParameterImplementor<?> parameter) {
final ProcedureParameterImplementor procParam = parameterMetadata.resolve( parameter );
ProcedureParameterBinding binding = bindingMap.get( procParam );
ProcedureParameterBindingImplementor binding = bindingMap.get( procParam );
if ( binding == null ) {
if ( ! parameterMetadata.containsReference( parameter ) ) {
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 );
}
@ -65,7 +69,7 @@ public class ProcedureParamBindings implements QueryParameterBindings {
@Override
public ProcedureParameterBinding<?> getBinding(String name) {
return getBinding( parameterMetadata.getQueryParameter( name ) );
return (ProcedureParameterBinding<?>) getBinding( parameterMetadata.getQueryParameter( name ) );
}
@Override
@ -74,7 +78,7 @@ public class ProcedureParamBindings implements QueryParameterBindings {
}
@Override
public void verifyParametersBound(boolean callable) {
public void validate() {
parameterMetadata.visitRegistrations(
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.query.internal.QueryParameterBindingImpl;
import org.hibernate.query.procedure.ProcedureParameterBinding;
import org.hibernate.query.procedure.spi.ProcedureParameterBindingImplementor;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.procedure.spi.ProcedureParameterBindingImplementor;
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.spi.QueryParameterBindingTypeResolver;
/**

View File

@ -6,13 +6,22 @@
*/
package org.hibernate.procedure.internal;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.util.Objects;
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.AllowableTemporalParameterType;
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.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
@ -111,4 +120,124 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
public int hashCode() {
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
*
* 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>.
* 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;
package org.hibernate.procedure.internal;
import java.util.ArrayList;
import java.util.Collections;
@ -13,35 +13,35 @@ import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
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.ParameterStrategy;
import org.hibernate.query.QueryParameter;
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.QueryParameterImplementor;
/**
* Specialized ParameterMetadataImplementor for callable queries implementing
* expandable parameter registrations
*
* @author Steve Ebersole
*/
public class ProcedureParameterMetadataImpl implements ParameterMetadataImplementor {
private final ProcedureCallImpl procedureCall;
private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN;
private List<ProcedureParameterImplementor<?>> parameters = new ArrayList<>();
private List<ProcedureParameterImplementor<?>> parameters;
public ProcedureParameterMetadataImpl(ProcedureCallImpl procedureCall) {
this.procedureCall = procedureCall;
@SuppressWarnings("WeakerAccess")
public ProcedureParameterMetadataImpl() {
}
public <R> ProcedureParameterMetadataImpl(ProcedureCallImpl procedureCall, NamedCallableQueryMemento memento) {
this( procedureCall );
@SuppressWarnings("WeakerAccess")
public ProcedureParameterMetadataImpl(NamedCallableQueryMemento memento, SharedSessionContractImplementor session) {
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 );
}
@Override
public void visitParameters(Consumer<QueryParameterImplementor<?>> consumer) {
if ( parameters != null ) {
parameters.forEach( consumer );
}
}
@Override
public boolean hasNamedParameters() {
return parameterStrategy == ParameterStrategy.NAMED;
@ -105,15 +112,11 @@ public class ProcedureParameterMetadataImpl implements ParameterMetadataImplemen
return parameters.contains( parameter );
}
@SuppressWarnings("WeakerAccess")
public ParameterStrategy getParameterStrategy() {
return parameterStrategy;
}
@Override
public void collectAllParameters(ParameterCollector collector) {
parameters.forEach( collector::collect );
}
@Override
public boolean hasAnyMatching(Predicate<QueryParameterImplementor<?>> filter) {
if ( parameters.isEmpty() ) {

View File

@ -10,8 +10,9 @@ import java.sql.CallableStatement;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
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.sql.exec.spi.JdbcCall;
/**
* @author Steve Ebersole

View File

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

View File

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

View File

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

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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;
package org.hibernate.procedure.spi;
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;
import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
/**
* User hook for applying transformations of the query result tuples (the result "row").
*
* 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}
* 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() {
return getProducer().getFactory().getQueryPlanCache()
return getProducer().getFactory().getQueryInterpretationCache()
.getHQLQueryPlan( getQueryString(), false, Collections.<String, Filter>emptyMap() )
.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.NamedResultSetMappingMemento;
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.sqm.tree.SqmStatement;
@ -131,8 +131,8 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
Map<String,HibernateException> errors = new HashMap<>();
final SemanticQueryProducer sqmProducer = queryEngine.getSemanticQueryProducer();
final QueryPlanCache queryPlanCache = queryEngine.getQueryPlanCache();
final boolean cachingEnabled = queryPlanCache.isEnabled();
final QueryInterpretationCache interpretationCache = queryEngine.getInterpretationCache();
final boolean cachingEnabled = interpretationCache.isEnabled();
// Check named HQL queries
log.debugf( "Checking %s named HQL queries", hqlMementoMap.size() );
@ -144,7 +144,7 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
if ( cachingEnabled ) {
// 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 ) {

View File

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

View File

@ -9,18 +9,18 @@ package org.hibernate.query.internal;
import java.util.function.Function;
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.sqm.tree.SqmStatement;
/**
* @author Steve Ebersole
*/
public class QueryPlanCacheDisabledImpl implements QueryPlanCache {
public class QueryInterpretationCacheDisabledImpl implements QueryInterpretationCache {
/**
* Singleton access
*/
public static final QueryPlanCacheDisabledImpl INSTANCE = new QueryPlanCacheDisabledImpl();
public static final QueryInterpretationCacheDisabledImpl INSTANCE = new QueryInterpretationCacheDisabledImpl();
@Override
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.spi.NonSelectQueryPlan;
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.sqm.tree.SqmStatement;
@ -23,7 +23,7 @@ import org.jboss.logging.Logger;
*
* @author Steve Ebersole
*/
public class QueryPlanCacheStandardImpl implements QueryPlanCache {
public class QueryInterpretationCacheStandardImpl implements QueryInterpretationCache {
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<String, SqmStatement<?>> sqmStatementCache;
public QueryPlanCacheStandardImpl(int maxQueryPlanCount) {
public QueryInterpretationCacheStandardImpl(int maxQueryPlanCount) {
log.debugf( "Starting QueryPlanCache(%s)", maxQueryPlanCount );
queryPlanCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
@ -88,13 +88,13 @@ public class QueryPlanCacheStandardImpl implements QueryPlanCache {
@Override
public SqmStatement getSqmStatement(String queryString) {
log.debugf( "Creating and caching SqmStatement - %s", queryString );
log.tracef( "#getSqmStatement( %s )", queryString );
return sqmStatementCache.get( queryString );
}
@Override
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
sqmStatementCache.putIfAbsent( queryString, sqmStatement );
}

View File

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

View File

@ -1,32 +1,60 @@
/*
* 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>.
* 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 org.hibernate.query.QueryParameter;
import org.hibernate.type.Type;
import java.util.Objects;
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
*
* 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).
* QueryParameter impl for named-parameters in HQL, JPQL or Criteria queries.
*
* @author Steve Ebersole
*/
public class QueryParameterNamedImpl<T> extends AbstractQueryParameterImpl<T> implements QueryParameter<T> {
private final String name;
private final int[] sourceLocations;
public class QueryParameterNamedImpl<T> extends AbstractQueryParameter<T> {
/**
* 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) {
super( expectedType );
return new QueryParameterNamedImpl<T>(
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.sourceLocations = sourceLocations;
}
@Override
@ -35,13 +63,8 @@ public class QueryParameterNamedImpl<T> extends AbstractQueryParameterImpl<T> im
}
@Override
public Integer getPosition() {
return null;
}
@Override
public int[] getSourceLocations() {
return sourceLocations;
public ParameterMemento toMemento() {
return session -> new QueryParameterNamedImpl( getName(), allowsMultiValuedBinding(), getHibernateType() );
}
@Override
@ -52,13 +75,12 @@ public class QueryParameterNamedImpl<T> extends AbstractQueryParameterImpl<T> im
if ( o == null || getClass() != o.getClass() ) {
return false;
}
QueryParameterNamedImpl<?> that = (QueryParameterNamedImpl<?>) o;
return getName().equals( that.getName() );
return Objects.equals( name, that.name );
}
@Override
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.FlushMode;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
/**
* Named Query mementos are stored in the QueryEngine's
@ -46,4 +47,8 @@ public interface NamedQueryMemento {
String getComment();
Map<String, Object> getHints();
interface ParameterMemento {
QueryParameterImplementor resolve(SharedSessionContractImplementor session);
}
}

View File

@ -6,30 +6,38 @@
*/
package org.hibernate.query.spi;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.persistence.Parameter;
import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryParameter;
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
/**
* @author Steve Ebersole
*/
public interface ParameterMetadataImplementor extends ParameterMetadata {
@FunctionalInterface
interface ParameterCollector {
<P extends QueryParameterImplementor<?>> void collect(P queryParameter);
void visitParameters(Consumer<QueryParameterImplementor<?>> consumer);
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);
@Override
QueryParameterImplementor<?> getQueryParameter(String name);
ProcedureParameterImplementor<?> getQueryParameter(String name);
@Override
QueryParameterImplementor<?> getQueryParameter(int positionLabel);
ProcedureParameterImplementor<?> getQueryParameter(int positionLabel);
@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.Incubating;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cfg.AvailableSettings;
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.metamodel.spi.MetamodelImplementor;
import org.hibernate.query.QueryLogger;
import org.hibernate.query.internal.QueryPlanCacheDisabledImpl;
import org.hibernate.query.internal.QueryPlanCacheStandardImpl;
import org.hibernate.query.internal.QueryInterpretationCacheDisabledImpl;
import org.hibernate.query.internal.QueryInterpretationCacheStandardImpl;
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
@ -38,7 +39,7 @@ import org.hibernate.service.ServiceRegistry;
public class QueryEngine {
public static QueryEngine from(
SessionFactoryImplementor sessionFactory,
NamedQueryRepository namedQueryRepository) {
MetadataImplementor metadata) {
return new QueryEngine(
sessionFactory.getMetamodel(),
sessionFactory.getServiceRegistry(),
@ -46,14 +47,14 @@ public class QueryEngine {
sessionFactory,
new SqmCreationOptionsStandard( sessionFactory ),
sessionFactory.getProperties(),
namedQueryRepository
metadata.buildNamedQueryRepository( sessionFactory )
);
}
private final NamedQueryRepository namedQueryRepository;
private final SqmCriteriaNodeBuilder criteriaBuilder;
private final SemanticQueryProducer semanticQueryProducer;
private final QueryPlanCache queryPlanCache;
private final QueryInterpretationCache interpretationCache;
private final SqmFunctionRegistry sqmFunctionRegistry;
public QueryEngine(
@ -72,7 +73,7 @@ public class QueryEngine {
serviceRegistry
);
this.queryPlanCache = buildQueryPlanCache( properties );
this.interpretationCache = buildQueryPlanCache( properties );
this.sqmFunctionRegistry = new SqmFunctionRegistry();
serviceRegistry.getService( JdbcServices.class )
@ -80,9 +81,11 @@ public class QueryEngine {
.getDialect()
.initializeFunctionRegistry( this );
runtimeOptions.getSqmFunctionRegistry().overlay( sqmFunctionRegistry );
getNamedQueryRepository().checkNamedQueries( this );
}
private static QueryPlanCache buildQueryPlanCache(Map properties) {
private static QueryInterpretationCache buildQueryPlanCache(Map properties) {
final boolean explicitUseCache = ConfigurationHelper.getBoolean(
AvailableSettings.QUERY_PLAN_CACHE_ENABLED,
properties,
@ -95,15 +98,15 @@ public class QueryEngine {
);
if ( explicitUseCache || ( explicitMaxPlanCount != null && explicitMaxPlanCount > 0 ) ) {
return new QueryPlanCacheStandardImpl(
return new QueryInterpretationCacheStandardImpl(
explicitMaxPlanCount != null
? explicitMaxPlanCount
: QueryPlanCacheStandardImpl.DEFAULT_QUERY_PLAN_MAX_COUNT
: QueryInterpretationCacheStandardImpl.DEFAULT_QUERY_PLAN_MAX_COUNT
);
}
else {
// disabled
return QueryPlanCacheDisabledImpl.INSTANCE;
return QueryInterpretationCacheDisabledImpl.INSTANCE;
}
}
@ -137,8 +140,8 @@ public class QueryEngine {
return semanticQueryProducer;
}
public QueryPlanCache getQueryPlanCache() {
return queryPlanCache;
public QueryInterpretationCache getInterpretationCache() {
return interpretationCache;
}
public SqmFunctionRegistry getSqmFunctionRegistry() {
@ -158,8 +161,8 @@ public class QueryEngine {
semanticQueryProducer.close();
}
if ( queryPlanCache != null ) {
queryPlanCache.close();
if ( interpretationCache != null ) {
interpretationCache.close();
}
if ( sqmFunctionRegistry != null ) {

View File

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

View File

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

View File

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

View File

@ -16,4 +16,6 @@ public interface QueryParameterImplementor<T> extends QueryParameter<T> {
void disallowMultiValuedBinding();
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.ResultListTransformer;
import org.hibernate.query.TupleTransformer;
import org.hibernate.query.spi.NameableQuery;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.type.Type;
@ -38,12 +39,16 @@ import org.hibernate.type.Type;
* @author Steve Ebersole
*/
@Incubating
public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQuery<R> {
public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQuery<R>, NameableQuery {
NativeQueryImplementor setCollectionKey(Serializable key);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// covariant overrides - NativeQuery
@Override
NamedNativeQueryMemento toMemento(String name);
@Override
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.FromClauseIndex;
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.sql.ast.produce.spi.SqlAstProcessingState;
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.SqmSelectToSqlAstConverter;
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
import org.hibernate.sql.exec.internal.RowTransformerJpaTupleImpl;
import org.hibernate.sql.exec.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.exec.internal.RowTransformerSingularReturnImpl;
import org.hibernate.sql.exec.internal.RowTransformerTupleTransformerAdapter;
import org.hibernate.sql.results.internal.RowTransformerJpaTupleImpl;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.internal.RowTransformerSingularReturnImpl;
import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
import org.hibernate.sql.exec.internal.TupleElementImpl;
import org.hibernate.sql.exec.spi.ExecutionContext;
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.QueryParameterBindings;
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.SelectQueryPlan;
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
@ -317,15 +317,15 @@ public class QuerySqmImpl<R>
SelectQueryPlan<R> queryPlan = null;
final QueryPlanCache.Key cacheKey = SqmInterpretationsKey.generateFrom( this );
final QueryInterpretationCache.Key cacheKey = SqmInterpretationsKey.generateFrom( this );
if ( cacheKey != null ) {
queryPlan = getSession().getFactory().getQueryEngine().getQueryPlanCache().getSelectQueryPlan( cacheKey );
queryPlan = getSession().getFactory().getQueryEngine().getInterpretationCache().getSelectQueryPlan( cacheKey );
}
if ( queryPlan == null ) {
queryPlan = buildSelectQueryPlan();
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;
final QueryPlanCache.Key cacheKey = SqmInterpretationsKey.generateNonSelectKey( this );
final QueryInterpretationCache.Key cacheKey = SqmInterpretationsKey.generateNonSelectKey( this );
if ( cacheKey != null ) {
queryPlan = getSession().getFactory().getQueryEngine().getQueryPlanCache().getNonSelectQueryPlan( cacheKey );
queryPlan = getSession().getFactory().getQueryEngine().getInterpretationCache().getNonSelectQueryPlan( cacheKey );
}
if ( queryPlan == null ) {
queryPlan = buildNonSelectQueryPlan();
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.TupleTransformer;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryPlanCache;
import org.hibernate.query.spi.QueryInterpretationCache;
/**
* @author Steve Ebersole
*/
public class SqmInterpretationsKey implements QueryPlanCache.Key {
public class SqmInterpretationsKey implements QueryInterpretationCache.Key {
@SuppressWarnings("WeakerAccess")
public static SqmInterpretationsKey generateFrom(QuerySqmImpl query) {
if ( !isCacheable( query ) ) {
@ -33,7 +33,7 @@ public class SqmInterpretationsKey implements QueryPlanCache.Key {
}
@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?
// - 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.query.NavigablePath;
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.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.query.NavigablePath;
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.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
*/
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.CoreMessageLogger;
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;
/**

View File

@ -15,7 +15,7 @@ import org.hibernate.query.sqm.tree.SqmVisitableNode;
import org.hibernate.sql.SqlExpressableType;
import org.hibernate.sql.ast.consume.spi.SelfRenderingExpression;
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.sqm.spi.SqmExpressionInterpretation;
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.tree.SqmTypedNode;
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.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.tree.SqmTypedNode;
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 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.tree.SqmTypedNode;
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 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.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 java.util.List;

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.tree.expression;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.sqm.NodeBuilder;
@ -110,7 +111,7 @@ public class SqmCriteriaParameter<T>
}
@Override
public ParameterMemento toMemento() {
public NamedCallableQueryMemento.ParameterMemento toMemento() {
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
* 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.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.internal.util.collections.CollectionHelper;
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.spi.DomainResult;
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.Set;
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
* domain results ({@link DomainResult}) descriptors.
*
* @see JdbcValuesMappingProducer#resolve
* @see JdbcValuesMappingDescriptor#resolve
*
* @author Steve Ebersole
*/
@ -27,13 +26,9 @@ public interface JdbcValuesMapping {
*/
Set<SqlSelection> getSqlSelections();
List<DomainResult<?>> getDomainResults();
List<DomainResult> getDomainResults();
default List<DomainResultAssembler<?>> resolveAssemblers(
List<DomainResultAssembler> resolveAssemblers(
Consumer<Initializer> initializerConsumer,
AssemblerCreationState creationState) {
return getDomainResults().stream()
.map( domainResult -> domainResult.createResultAssembler( initializerConsumer, creationState ) )
.collect( Collectors.toList() );
}
AssemblerCreationState creationState);
}

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;
/**
* 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
*/
public interface RowProcessingState extends ExecutionContext {
/**
* Access to the "parent state" related to the overall processing
* of the results.
* Access to the state related to the overall processing of the results.
*/
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();
/**
* Locate the Initalizer registered for the given 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 org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.internal.CoreLogging;

View File

@ -16,26 +16,19 @@ import java.sql.SQLException;
*/
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.
* @param value The value to bind.
* @param index The position at which to bind the value within the prepared statement
* @param options The options.
* @apiNote Also works for callables since {@link CallableStatement} extends
* {@link PreparedStatement}
*
* @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.
*
* @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.
* Bind a value to a callable statement by name
*
* @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;
/**
* 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
*/
@ -19,17 +20,21 @@ public interface ValueExtractor<X> {
/**
* Extract value from result set
*
* @param rs The result set from which to extract the value
* @param name The name by which to extract the value from the result set
* @param options The options
*
* @return The extracted value
* @throws SQLException Indicates a JDBC error occurred.
*/
X extract(ResultSet rs, String name, WrapperOptions options) throws SQLException;
/**
* Extract value from a callable output parameter by index
*
* @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;
public X extract(CallableStatement statement, String[] paramNames, WrapperOptions options) throws SQLException;
/**
* Extract value from a callable output parameter by name
*
* @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.
*
* @todo Definitely could use a better name
*
* @author Steve Ebersole
*/
public interface WrapperOptions {
@ -26,14 +24,14 @@ public interface WrapperOptions {
*
* @return {@code true}/{@code false}
*/
public boolean useStreamForLobBinding();
boolean useStreamForLobBinding();
/**
* Obtain access to the {@link LobCreator}
*
* @return The LOB creator
*/
public LobCreator getLobCreator();
LobCreator getLobCreator();
/**
* 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.
*/
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor);
SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor);
/**
* 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}
*/
public TimeZone getJdbcTimeZone();
TimeZone getJdbcTimeZone();
}

View File

@ -44,7 +44,7 @@ public class CompositeIdTest extends BaseCoreFunctionalTestCase {
@Test
public void testNonDistinctCountOfEntityWithCompositeId() {
// 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",
false,
Collections.EMPTY_MAP
@ -70,7 +70,7 @@ public class CompositeIdTest extends BaseCoreFunctionalTestCase {
public void testDistinctCountOfEntityWithCompositeId() {
// today we do not account for Dialects supportsTupleDistinctCounts() is false. though really the only
// "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",
false,
Collections.EMPTY_MAP

View File

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

View File

@ -14,7 +14,6 @@ import javax.persistence.Id;
import java.util.Collections;
import org.hibernate.Filter;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
@ -23,13 +22,10 @@ import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals;
@ -81,7 +77,7 @@ public class TupleSupportTest extends BaseUnitTestCase {
@Test
public void testImplicitTupleNotEquals() {
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() );
assertEquals( 1, queryPlan.getSqlStrings().length );
@ -92,7 +88,7 @@ public class TupleSupportTest extends BaseUnitTestCase {
@Test
public void testImplicitTupleNotInList() {
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() );
assertEquals( 1, queryPlan.getSqlStrings().length );

View File

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

View File

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