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:
parent
46e27d7f46
commit
8d0ff71dfc
|
@ -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 {
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ) ) );
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() );
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ public interface AllowableOutputParameterType<J> extends AllowableParameterType<
|
|||
*/
|
||||
SqlTypeDescriptor getSqlTypeDescriptor();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Perform the extraction
|
||||
*
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() ) {
|
|
@ -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
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.procedure.spi;
|
||||
|
||||
import org.hibernate.procedure.FunctionReturn;
|
||||
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ public interface ProcedureCallImplementor<R> extends ProcedureCall, QueryImpleme
|
|||
return list();
|
||||
}
|
||||
|
||||
ParameterStrategy getParameterStrategy();
|
||||
|
||||
@Override
|
||||
default R getSingleResult() {
|
||||
return uniqueResult();
|
||||
|
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
|
@ -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 );
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -25,4 +25,6 @@ public interface QueryImplementor<R> extends Query<R> {
|
|||
void setOptionalEntityName(String entityName);
|
||||
|
||||
void setOptionalObject(Object optionalObject);
|
||||
|
||||
QueryParameterBindings getParameterBindings();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.hibernate.query.sqm.tree.SqmStatement;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface QueryPlanCache {
|
||||
public interface QueryInterpretationCache {
|
||||
interface Key {
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -16,4 +16,6 @@ public interface QueryParameterImplementor<T> extends QueryParameter<T> {
|
|||
void disallowMultiValuedBinding();
|
||||
|
||||
void applyAnticipatedType(AllowableParameterType type);
|
||||
|
||||
NamedQueryMemento.ParameterMemento toMemento();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" +
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ) );
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue