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 ProcedureCal
This commit is contained in:
parent
3a761361fe
commit
f52e305ffb
|
@ -159,7 +159,7 @@ import org.hibernate.persister.entity.OuterJoinLoadable;
|
|||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.UnknownSqlResultSetMappingException;
|
||||
import org.hibernate.query.UnknownSqlResultSetMappingException;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
|
||||
|
|
|
@ -454,4 +454,8 @@ public final class ArrayHelper {
|
|||
System.out.println( "[" + i + "] -> " + batchSizes[i] );
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEmpty(Object[] array) {
|
||||
return array == null || array.length == 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,13 +13,21 @@ import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardBasicValueConverter<O,R> implements BasicValueConverter<O,R> {
|
||||
public class NoOpBasicValueConverter<O,R> implements BasicValueConverter<O,R> {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final StandardBasicValueConverter INSTANCE = new StandardBasicValueConverter();
|
||||
public static final NoOpBasicValueConverter INSTANCE = new NoOpBasicValueConverter();
|
||||
|
||||
private StandardBasicValueConverter() {
|
||||
/**
|
||||
* Typed access to the singleton
|
||||
*/
|
||||
public static <O,R> NoOpBasicValueConverter<O,R> instance() {
|
||||
//noinspection unchecked
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private NoOpBasicValueConverter() {
|
||||
}
|
||||
|
||||
@Override
|
|
@ -15,6 +15,9 @@ package org.hibernate.metamodel.model.convert.spi;
|
|||
* * implicitly, based on the Java type (e.g., enums)
|
||||
* * etc
|
||||
*
|
||||
* @param <O> The Java type we can use to represent the domain (object) type
|
||||
* @param <R> The Java type we can use to represent the relational type
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface BasicValueConverter<O,R> {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.metamodel.model.convert.spi;
|
||||
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
|
||||
/**
|
||||
* Describes a part of the domain model to which a value converter can be applied
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ConvertibleValueMapping<O> extends SqmExpressable<O> {
|
||||
/**
|
||||
* Get the value converter associated with this value mapping. May
|
||||
* return {@code null}
|
||||
*/
|
||||
<R> BasicValueConverter<O,R> getValueConverter();
|
||||
}
|
|
@ -6,6 +6,11 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
/**
|
||||
* Specialization of DomainType for types that can be used as a
|
||||
* parameter output for a {@link org.hibernate.procedure.ProcedureCall}
|
||||
|
@ -16,4 +21,38 @@ package org.hibernate.metamodel.model.domain;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface AllowableOutputParameterType<J> extends AllowableParameterType<J> {
|
||||
/**
|
||||
* Can the given instance of this type actually perform the parameter value extractions?
|
||||
*
|
||||
* @return {@code true} indicates that @{link #extract} calls will not fail due to {@link IllegalStateException}.
|
||||
*/
|
||||
boolean canDoExtraction();
|
||||
|
||||
/**
|
||||
* Perform the extraction
|
||||
*
|
||||
* @param statement The CallableStatement from which to extract the parameter value(s).
|
||||
* @param startIndex The parameter index from which to start extracting; assumes the values (if multiple) are contiguous
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return The extracted value.
|
||||
*
|
||||
* @throws SQLException Indicates an issue calling into the CallableStatement
|
||||
* @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction}
|
||||
*/
|
||||
J extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session) throws SQLException;
|
||||
|
||||
/**
|
||||
* Perform the extraction
|
||||
*
|
||||
* @param statement The CallableStatement from which to extract the parameter value(s).
|
||||
* @param paramNames The parameter names.
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return The extracted value.
|
||||
*
|
||||
* @throws SQLException Indicates an issue calling into the CallableStatement
|
||||
* @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction}
|
||||
*/
|
||||
J extract(CallableStatement statement, String[] paramNames, SharedSessionContractImplementor session) throws SQLException;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import javax.persistence.metamodel.EmbeddableType;
|
|||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.metamodel.spi.DomainMetamodel;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
@ -24,6 +25,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
* @author Steve Ebersole
|
||||
* @see DomainMetamodel
|
||||
*/
|
||||
@Incubating
|
||||
public interface JpaMetamodel extends javax.persistence.metamodel.Metamodel {
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -53,10 +55,29 @@ public interface JpaMetamodel extends javax.persistence.metamodel.Metamodel {
|
|||
*/
|
||||
<X> EntityDomainType<X> resolveHqlEntityReference(String entityName);
|
||||
|
||||
/**
|
||||
* Visitation over all managed types via Consumer
|
||||
*/
|
||||
void visitManagedTypes(Consumer<ManagedDomainType<?>> action);
|
||||
|
||||
/**
|
||||
* Same as {@link #managedType} except {@code null} is returned rather
|
||||
* than throwing an exception
|
||||
*/
|
||||
<X> ManagedDomainType<X> findManagedType(Class<X> cls);
|
||||
|
||||
/**
|
||||
* Visitation over all entity types via Consumer
|
||||
*/
|
||||
void visitEntityTypes(Consumer<EntityDomainType<?>> action);
|
||||
|
||||
/**
|
||||
* Same as {@link #entity} except {@code null} is returned rather
|
||||
* than throwing an exception
|
||||
*/
|
||||
<X> EntityDomainType<X> findEntityType(Class<X> cls);
|
||||
|
||||
/
|
||||
void visitRootEntityTypes(Consumer<EntityDomainType<?>> action);
|
||||
|
||||
void visitEmbeddables(Consumer<EmbeddableDomainType<?>> action);
|
||||
|
|
|
@ -361,8 +361,10 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
|||
type = embeddableDescriptorMap.get( cls );
|
||||
}
|
||||
if ( type == null ) {
|
||||
// per JPA
|
||||
throw new IllegalArgumentException( "Not a managed type: " + cls );
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (ManagedDomainType<X>) type;
|
||||
}
|
||||
|
|
|
@ -9,13 +9,16 @@ package org.hibernate.metamodel.spi;
|
|||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.UnknownEntityTypeException;
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.graph.RootGraph;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -23,13 +26,43 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface DomainMetamodel {
|
||||
/**
|
||||
* Access to the JPA metamodel sub-set of the overall run-time metamodel
|
||||
*
|
||||
* @apiNote The distinction is mainly used in building SQM trees, which rely
|
||||
* on the JPA type subset
|
||||
*/
|
||||
JpaMetamodel getJpaMetamodel();
|
||||
|
||||
/**
|
||||
* The TypeConfiguration this metamodel is associated with
|
||||
*/
|
||||
default TypeConfiguration getTypeConfiguration() {
|
||||
return getJpaMetamodel().getTypeConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a Java type, determine the corresponding AllowableParameterType to
|
||||
* use implicitly
|
||||
*/
|
||||
default <T> AllowableParameterType<T> resolveQueryParameterType(Class<T> javaType) {
|
||||
final BasicType basicType = getTypeConfiguration().getBasicTypeForJavaType( javaType );
|
||||
if ( basicType != null ) {
|
||||
//noinspection unchecked
|
||||
return basicType;
|
||||
}
|
||||
|
||||
final ManagedDomainType<T> managedType = getJpaMetamodel().findManagedType( javaType );
|
||||
if ( managedType instanceof AllowableParameterType ) {
|
||||
//noinspection unchecked
|
||||
return (AllowableParameterType) managedType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an (assumed) entity instance, determine its descriptor
|
||||
*
|
||||
|
@ -184,5 +217,4 @@ public interface DomainMetamodel {
|
|||
List<RootGraph<?>> findRootGraphsForType(Class baseEntityJavaType);
|
||||
List<RootGraph<?>> findRootGraphsForType(String baseEntityName);
|
||||
List<RootGraph<?>> findRootGraphsForType(EntityPersister baseEntityDescriptor);
|
||||
|
||||
}
|
||||
|
|
|
@ -190,6 +190,19 @@ public interface EntityPersister extends EntityDefinition {
|
|||
*/
|
||||
Serializable[] getQuerySpaces();
|
||||
|
||||
/**
|
||||
* Returns an array of objects that identify spaces in which properties of
|
||||
* this entity are persisted, for instances of this class and its subclasses.
|
||||
* <p/>
|
||||
* Much like {@link #getPropertySpaces()}, except that here we include subclass
|
||||
* entity spaces.
|
||||
*
|
||||
* @return The query spaces.
|
||||
*/
|
||||
default String[] getSynchronizedQuerySpaces() {
|
||||
return (String[]) getQuerySpaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this entity supports dynamic proxies.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.hibernate.query.procedure.ProcedureParameter;
|
||||
|
||||
/**
|
||||
* Describes the function return for ProcedureCalls that represent calls to
|
||||
* a function ({@code "{? = call ...} syntax) rather that a proc ({@code {call ...} syntax)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface FunctionReturn<T> extends ProcedureParameter<T> {
|
||||
int getJdbcTypeCode();
|
||||
}
|
|
@ -1,31 +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;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
|
||||
/**
|
||||
* Describes an input value binding for any IN/INOUT parameters.
|
||||
*/
|
||||
public interface ParameterBind<T> extends QueryParameterBinding<T> {
|
||||
/**
|
||||
* Retrieves the bound value.
|
||||
*
|
||||
* @return The bound value.
|
||||
*/
|
||||
T getValue();
|
||||
|
||||
/**
|
||||
* If {@code <T>} represents a DATE/TIME type value, JPA usually allows specifying the particular parts of
|
||||
* the DATE/TIME value to be bound. This value represents the particular part the user requested to be bound.
|
||||
*
|
||||
* @return The explicitly supplied TemporalType.
|
||||
*/
|
||||
TemporalType getExplicitTemporalType();
|
||||
}
|
|
@ -9,7 +9,7 @@ package org.hibernate.procedure;
|
|||
import org.hibernate.HibernateException;
|
||||
|
||||
/**
|
||||
* Thrown to indicate a misuse of a {@link ParameterRegistration}
|
||||
* Thrown to indicate a misuse of a parameter
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
|
|
@ -1,114 +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;
|
||||
|
||||
import javax.persistence.ParameterMode;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.query.procedure.ProcedureParameter;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Describes a registered procedure/function parameter.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ParameterRegistration<T> extends ProcedureParameter<T> {
|
||||
/**
|
||||
* The name under which this parameter was registered. Can be {@code null} which should indicate that
|
||||
* positional registration was used (and therefore {@link #getPosition()} should return non-null.
|
||||
*
|
||||
* @return The name;
|
||||
*/
|
||||
@Override
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* The position at which this parameter was registered. Can be {@code null} which should indicate that
|
||||
* named registration was used (and therefore {@link #getName()} should return non-null.
|
||||
*
|
||||
* @return The name;
|
||||
*/
|
||||
@Override
|
||||
Integer getPosition();
|
||||
|
||||
/**
|
||||
* Return the Java type of the parameter.
|
||||
*
|
||||
* @return The Java type of the parameter.
|
||||
* @deprecated Call {@link #getParameterType()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default Class<T> getType() {
|
||||
return getParameterType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the parameter "mode" which describes how the parameter is defined in the actual database procedure
|
||||
* definition (is it an INPUT parameter? An OUTPUT parameter? etc).
|
||||
*
|
||||
* @return The parameter mode.
|
||||
*/
|
||||
@Override
|
||||
ParameterMode getMode();
|
||||
|
||||
/**
|
||||
* Controls how unbound values for this IN/INOUT parameter registration will be handled prior to
|
||||
* execution. There are 2 possible options to handle it:<ul>
|
||||
* <li>bind the NULL to the parameter</li>
|
||||
* <li>do not bind the NULL to the parameter</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* The reason for the distinction comes from default values defined on the corresponding
|
||||
* database procedure/function argument. Any time a value (including NULL) is bound to the
|
||||
* argument, its default value will not be used. So effectively this setting controls
|
||||
* whether the NULL should be interpreted as "pass the NULL" or as "apply the argument default".
|
||||
* <p/>
|
||||
* The (global) default this setting is defined by {@link org.hibernate.cfg.AvailableSettings#PROCEDURE_NULL_PARAM_PASSING}
|
||||
*
|
||||
* @param enabled {@code true} indicates that the NULL should be passed; {@code false} indicates it should not.
|
||||
*
|
||||
* @deprecated (since 6.0) : see {@link #isPassNullsEnabled}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
void enablePassingNulls(boolean enabled);
|
||||
|
||||
/**
|
||||
* Set the Hibernate mapping type for this parameter.
|
||||
*
|
||||
* @param type The Hibernate mapping type.
|
||||
*/
|
||||
void setHibernateType(Type type);
|
||||
|
||||
/**
|
||||
* Retrieve the binding associated with this parameter. The binding is only relevant for INPUT parameters. Can
|
||||
* return {@code null} if nothing has been bound yet. To bind a value to the parameter use one of the
|
||||
* {@link #bindValue} methods.
|
||||
*
|
||||
* @return The parameter binding
|
||||
*/
|
||||
ParameterBind<T> getBind();
|
||||
|
||||
/**
|
||||
* Bind a value to the parameter. How this value is bound to the underlying JDBC CallableStatement is
|
||||
* totally dependent on the Hibernate type.
|
||||
*
|
||||
* @param value The value to bind.
|
||||
*/
|
||||
void bindValue(T value);
|
||||
|
||||
/**
|
||||
* Bind a value to the parameter, using just a specified portion of the DATE/TIME value. It is illegal to call
|
||||
* this form if the parameter is not DATE/TIME type. The Hibernate type is circumvented in this case and
|
||||
* an appropriate "precision" Type is used instead.
|
||||
*
|
||||
* @param value The value to bind
|
||||
* @param explicitTemporalType An explicitly supplied TemporalType.
|
||||
*/
|
||||
void bindValue(T value, TemporalType explicitTemporalType);
|
||||
}
|
|
@ -7,38 +7,86 @@
|
|||
package org.hibernate.procedure;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.ParameterMode;
|
||||
import javax.persistence.StoredProcedureQuery;
|
||||
|
||||
import org.hibernate.BasicQueryContract;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.SynchronizeableQuery;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.query.CommonQueryContract;
|
||||
import org.hibernate.query.procedure.ProcedureParameter;
|
||||
import org.hibernate.query.spi.NameableQuery;
|
||||
|
||||
/**
|
||||
* Defines support for executing database stored procedures and functions
|
||||
* Defines support for executing database stored procedures and functions.
|
||||
* <p/>
|
||||
* Note that here we use the terms "procedure" and "function" as follows:<ul>
|
||||
* <li>procedure is a named database executable we expect to call via : {@code {call procedureName(...)}}</li>
|
||||
* <li>function is a named database executable we expect to call via : {@code {? = call functionName(...)}}</li>
|
||||
* </ul>
|
||||
* Unless explicitly specified, the ProcedureCall is assumed to follow the
|
||||
* procedure call syntax. To explicitly specify that this should be a function
|
||||
* call, use {@link #markAsFunctionCall}. JPA users could either:<ul>
|
||||
* <li>use {@code storedProcedureQuery.unwrap( ProcedureCall.class }.markAsFunctionCall()</li>
|
||||
* <li>set the {@link #FUNCTION_RETURN_TYPE_HINT} hint (avoids casting to Hibernate-specific classes)</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* When using function-call syntax:<ul>
|
||||
* <li>parameters must be registered by position (not name)</li>
|
||||
* <li>The first parameter is considered to be the function return (the `?` before the call)</li>
|
||||
* <li>the first parameter must have mode of OUT, INOUT or REF_CURSOR; IN is invalid</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* In some cases, based on the Dialect, we will have other validations and
|
||||
* assumptions as well. For example, on PGSQL, whenever we see a REF_CURSOR mode
|
||||
* parameter, we know that:<ul>
|
||||
* <li>
|
||||
* this will be a function call (so we call {@link #markAsFunctionCall} implicitly) because
|
||||
* that is the only way PGSQL supports returning REF_CURSOR results.
|
||||
* </li>
|
||||
* <li>there can be only one REF_CURSOR mode parameter</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ProcedureCall extends BasicQueryContract<CommonQueryContract>, SynchronizeableQuery, StoredProcedureQuery {
|
||||
@Override
|
||||
ProcedureCall addSynchronizedQuerySpace(String querySpace);
|
||||
|
||||
@Override
|
||||
ProcedureCall addSynchronizedEntityName(String entityName) throws MappingException;
|
||||
|
||||
@Override
|
||||
ProcedureCall addSynchronizedEntityClass(Class entityClass) throws MappingException;
|
||||
public interface ProcedureCall
|
||||
extends CommonQueryContract, SynchronizeableQuery, StoredProcedureQuery, NameableQuery, AutoCloseable {
|
||||
/**
|
||||
* The hint key (for use with JPA's "hint system") indicating the function's return JDBC type code
|
||||
* (aka, {@link java.sql.Types} code)
|
||||
*/
|
||||
String FUNCTION_RETURN_TYPE_HINT = "hibernate.procedure.function_return_jdbc_type_code";
|
||||
|
||||
/**
|
||||
* Get the name of the stored procedure to be called.
|
||||
* Get the name of the stored procedure (or function) to be called.
|
||||
*
|
||||
* @return The procedure name.
|
||||
*/
|
||||
String getProcedureName();
|
||||
|
||||
/**
|
||||
* Does this ProcedureCall represent a call to a database FUNCTION (as opposed
|
||||
* to a PROCEDURE call)?
|
||||
*
|
||||
* NOTE : this will only report whether this ProcedureCall was marked
|
||||
* as a function via call to {@link #markAsFunctionCall}. Specifically
|
||||
* will not return {@code true} when using JPA query hint.
|
||||
*
|
||||
* @return {@code true} indicates that this ProcedureCall represents a
|
||||
* function call; {@code false} indicates a procedure call.
|
||||
*/
|
||||
boolean isFunctionCall();
|
||||
|
||||
/**
|
||||
* Mark this ProcedureCall as representing a call to a database function,
|
||||
* rather than a database procedure.
|
||||
*
|
||||
* @param sqlType The {@link java.sql.Types} code for the function return
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
ProcedureCall markAsFunctionCall(int sqlType);
|
||||
|
||||
/**
|
||||
* Basic form for registering a positional parameter.
|
||||
*
|
||||
|
@ -49,7 +97,7 @@ public interface ProcedureCall extends BasicQueryContract<CommonQueryContract>,
|
|||
*
|
||||
* @return The parameter registration memento
|
||||
*/
|
||||
<T> ParameterRegistration<T> registerParameter(int position, Class<T> type, ParameterMode mode);
|
||||
<T> ProcedureParameter<T> registerParameter(int position, Class<T> type, ParameterMode mode);
|
||||
|
||||
/**
|
||||
* Chained form of {@link #registerParameter(int, Class, javax.persistence.ParameterMode)}
|
||||
|
@ -60,7 +108,7 @@ public interface ProcedureCall extends BasicQueryContract<CommonQueryContract>,
|
|||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
ProcedureCall registerParameter0(int position, Class type, ParameterMode mode);
|
||||
<T> ProcedureCall registerParameter0(int position, Class<T> type, ParameterMode mode);
|
||||
|
||||
/**
|
||||
* Retrieve a previously registered parameter memento by the position under which it was registered.
|
||||
|
@ -72,7 +120,7 @@ public interface ProcedureCall extends BasicQueryContract<CommonQueryContract>,
|
|||
* @throws ParameterStrategyException If the ProcedureCall is defined using named parameters
|
||||
* @throws NoSuchParameterException If no parameter with that position exists
|
||||
*/
|
||||
ParameterRegistration getParameterRegistration(int position);
|
||||
ProcedureParameter getParameterRegistration(int position);
|
||||
|
||||
/**
|
||||
* Basic form for registering a named parameter.
|
||||
|
@ -87,7 +135,7 @@ public interface ProcedureCall extends BasicQueryContract<CommonQueryContract>,
|
|||
* @throws NamedParametersNotSupportedException When the underlying database is known to not support
|
||||
* named procedure parameters.
|
||||
*/
|
||||
<T> ParameterRegistration<T> registerParameter(String parameterName, Class<T> type, ParameterMode mode)
|
||||
<T> ProcedureParameter<T> registerParameter(String parameterName, Class<T> type, ParameterMode mode)
|
||||
throws NamedParametersNotSupportedException;
|
||||
|
||||
/**
|
||||
|
@ -115,14 +163,14 @@ public interface ProcedureCall extends BasicQueryContract<CommonQueryContract>,
|
|||
* @throws ParameterStrategyException If the ProcedureCall is defined using positional parameters
|
||||
* @throws NoSuchParameterException If no parameter with that name exists
|
||||
*/
|
||||
ParameterRegistration getParameterRegistration(String name);
|
||||
ProcedureParameter getParameterRegistration(String name);
|
||||
|
||||
/**
|
||||
* Retrieve all registered parameters.
|
||||
*
|
||||
* @return The (immutable) list of all registered parameters.
|
||||
*/
|
||||
List<ParameterRegistration> getRegisteredParameters();
|
||||
List<ProcedureParameter> getRegisteredParameters();
|
||||
|
||||
/**
|
||||
* Retrieves access to outputs of this procedure call. Can be called multiple times, returning the same
|
||||
|
@ -136,18 +184,22 @@ public interface ProcedureCall extends BasicQueryContract<CommonQueryContract>,
|
|||
ProcedureOutputs getOutputs();
|
||||
|
||||
/**
|
||||
* Extract the disconnected representation of this call. Used in HEM to allow redefining a named query
|
||||
*
|
||||
* @param hints The hints to incorporate into the memento
|
||||
*
|
||||
* @return The memento
|
||||
* Release the underlying JDBC {@link java.sql.CallableStatement}
|
||||
*/
|
||||
NamedCallableQueryMemento extractMemento(Map<String, Object> hints);
|
||||
@Override
|
||||
default void close() {
|
||||
getOutputs().release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the disconnected representation of this call. Used in HEM to allow redefining a named query
|
||||
* *
|
||||
* @return The memento
|
||||
*/
|
||||
NamedCallableQueryMemento extractMemento();
|
||||
@Override
|
||||
ProcedureCall addSynchronizedQuerySpace(String querySpace);
|
||||
|
||||
@Override
|
||||
ProcedureCall addSynchronizedEntityName(String entityName) throws MappingException;
|
||||
|
||||
@Override
|
||||
ProcedureCall addSynchronizedEntityClass(Class entityClass) throws MappingException;
|
||||
|
||||
@Override
|
||||
NamedCallableQueryMemento toMemento(String name);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.procedure;
|
||||
|
||||
import org.hibernate.query.procedure.ProcedureParameter;
|
||||
import org.hibernate.result.Outputs;
|
||||
|
||||
/**
|
||||
|
@ -21,13 +22,13 @@ public interface ProcedureOutputs extends Outputs {
|
|||
* Should NOT be called for parameters registered as REF_CURSOR. REF_CURSOR parameters should be
|
||||
* accessed via the returns (see {@link #getNextOutput}
|
||||
*
|
||||
* @param parameterRegistration The parameter's registration memento.
|
||||
* @param parameter The parameter's registration memento.
|
||||
*
|
||||
* @return The output value.
|
||||
*
|
||||
* @see ProcedureCall#registerParameter(String, Class, javax.persistence.ParameterMode)
|
||||
*/
|
||||
public <T> T getOutputParameterValue(ParameterRegistration<T> parameterRegistration);
|
||||
<T> T getOutputParameterValue(ProcedureParameter<T> parameter);
|
||||
|
||||
/**
|
||||
* Retrieve the value of an OUTPUT parameter by the name under which the parameter was registered.
|
||||
|
@ -41,7 +42,7 @@ public interface ProcedureOutputs extends Outputs {
|
|||
*
|
||||
* @see ProcedureCall#registerParameter(String, Class, javax.persistence.ParameterMode)
|
||||
*/
|
||||
public Object getOutputParameterValue(String name);
|
||||
Object getOutputParameterValue(String name);
|
||||
|
||||
/**
|
||||
* Retrieve the value of an OUTPUT parameter by the name position under which the parameter was registered.
|
||||
|
@ -55,5 +56,5 @@ public interface ProcedureOutputs extends Outputs {
|
|||
*
|
||||
* @see ProcedureCall#registerParameter(int, Class, javax.persistence.ParameterMode)
|
||||
*/
|
||||
public Object getOutputParameterValue(int position);
|
||||
Object getOutputParameterValue(int position);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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 java.sql.Types;
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
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.ProcedureCallImplementor;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class FunctionReturnImpl implements FunctionReturnImplementor {
|
||||
private final ProcedureCallImplementor procedureCall;
|
||||
private int jdbcTypeCode;
|
||||
|
||||
private AllowableOutputParameterType<?> ormType;
|
||||
|
||||
public FunctionReturnImpl(ProcedureCallImplementor procedureCall, int jdbcTypeCode) {
|
||||
this.procedureCall = procedureCall;
|
||||
this.jdbcTypeCode = jdbcTypeCode;
|
||||
}
|
||||
|
||||
public FunctionReturnImpl(ProcedureCallImplementor procedureCall, AllowableOutputParameterType ormType) {
|
||||
this.procedureCall = procedureCall;
|
||||
this.jdbcTypeCode = ormType.getSqlTypeDescriptor().getJdbcTypeCode();
|
||||
|
||||
this.ormType = ormType;
|
||||
}
|
||||
|
||||
|
||||
public JdbcCallFunctionReturn toJdbcFunctionReturn(SharedSessionContractImplementor persistenceContext) {
|
||||
final AllowableParameterType ormType;
|
||||
final JdbcCallRefCursorExtractorImpl refCursorExtractor;
|
||||
final JdbcCallParameterExtractorImpl parameterExtractor;
|
||||
|
||||
if ( getJdbcTypeCode() == Types.REF_CURSOR ) {
|
||||
refCursorExtractor = new JdbcCallRefCursorExtractorImpl( null, 0 );
|
||||
ormType = null;
|
||||
parameterExtractor = null;
|
||||
}
|
||||
else {
|
||||
|
||||
final TypeConfiguration typeConfiguration = persistenceContext.getFactory().getMetamodel().getTypeConfiguration();
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = typeConfiguration.getSqlTypeDescriptorRegistry()
|
||||
.getDescriptor( getJdbcTypeCode() );
|
||||
final JavaTypeDescriptor javaTypeMapping = sqlTypeDescriptor
|
||||
.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
ormType = typeConfiguration.getBasicTypeRegistry().getBasicType( javaTypeMapping.getJavaType() );
|
||||
parameterExtractor = new JdbcCallParameterExtractorImpl( procedureCall.getProcedureName(), null, 0, ormType );
|
||||
refCursorExtractor = null;
|
||||
}
|
||||
|
||||
return new JdbcCallFunctionReturnImpl( getJdbcTypeCode(), ormType, parameterExtractor, refCursorExtractor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return jdbcTypeCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllowableParameterType getHibernateType() {
|
||||
return ormType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPosition() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterMode getMode() {
|
||||
return ParameterMode.OUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getParameterType() {
|
||||
return ormType == null ? null : ormType.getJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disallowMultiValuedBinding() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowsMultiValuedBinding() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@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 );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -15,13 +15,13 @@ import org.hibernate.CacheMode;
|
|||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
|
||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
||||
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
|
||||
import org.hibernate.query.spi.AbstractNamedQueryMemento;
|
||||
import org.hibernate.query.spi.NamedQueryMemento;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Implementation of NamedCallableQueryMemento
|
||||
|
@ -85,6 +85,31 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
|
|||
return callableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParameterMemento> getParameterMementos() {
|
||||
return parameterMementos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterStrategy getParameterStrategy() {
|
||||
return parameterStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getResultSetMappingNames() {
|
||||
return resultSetMappingNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class[] getResultSetMappingClasses() {
|
||||
return resultSetMappingClasses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getQuerySpaces() {
|
||||
return querySpaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureCall makeProcedureCall(SharedSessionContractImplementor session) {
|
||||
return new ProcedureCallImpl( session, this );
|
||||
|
@ -120,32 +145,22 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
|
|||
private final String name;
|
||||
private final ParameterMode mode;
|
||||
private final Class type;
|
||||
private final Type hibernateType;
|
||||
private final boolean passNulls;
|
||||
private final AllowableParameterType hibernateType;
|
||||
|
||||
/**
|
||||
* Create the memento
|
||||
*
|
||||
* @param position The parameter position
|
||||
* @param name The parameter name
|
||||
* @param mode The parameter mode
|
||||
* @param type The Java type of the parameter
|
||||
* @param hibernateType The Hibernate Type.
|
||||
* @param passNulls Should NULL values to passed to the database?
|
||||
*/
|
||||
public ParameterMementoImpl(
|
||||
int position,
|
||||
String name,
|
||||
ParameterMode mode,
|
||||
Class type,
|
||||
Type hibernateType,
|
||||
boolean passNulls) {
|
||||
AllowableParameterType hibernateType) {
|
||||
this.position = position;
|
||||
this.name = name;
|
||||
this.mode = mode;
|
||||
this.type = type;
|
||||
this.hibernateType = hibernateType;
|
||||
this.passNulls = passNulls;
|
||||
}
|
||||
|
||||
public Integer getPosition() {
|
||||
|
@ -164,16 +179,12 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
|
|||
return type;
|
||||
}
|
||||
|
||||
public Type getHibernateType() {
|
||||
public AllowableParameterType getHibernateType() {
|
||||
return hibernateType;
|
||||
}
|
||||
|
||||
public boolean isPassNullsEnabled() {
|
||||
return passNulls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterRegistrationImplementor resolve(SharedSessionContractImplementor session) {
|
||||
public ProcedureParameterImplementor resolve(SharedSessionContractImplementor session) {
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
|
||||
|
@ -184,14 +195,13 @@ public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento imp
|
|||
*
|
||||
* @return The memento
|
||||
*/
|
||||
public static ParameterMementoImpl fromRegistration(ParameterRegistrationImplementor registration) {
|
||||
public static ParameterMementoImpl fromRegistration(ProcedureParameterImplementor registration) {
|
||||
return new ParameterMementoImpl(
|
||||
registration.getPosition(),
|
||||
registration.getName(),
|
||||
registration.getMode(),
|
||||
registration.getParameterType(),
|
||||
registration.getHibernateType(),
|
||||
registration.isPassNullsEnabled()
|
||||
registration.getHibernateType()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import java.util.Collections;
|
|||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.FlushModeType;
|
||||
|
@ -24,40 +23,48 @@ import javax.persistence.NoResultException;
|
|||
import javax.persistence.NonUniqueResultException;
|
||||
import javax.persistence.Parameter;
|
||||
import javax.persistence.ParameterMode;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.TransactionRequiredException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.query.spi.AbstractQuery;
|
||||
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.graph.GraphSemantic;
|
||||
import org.hibernate.graph.RootGraph;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.procedure.NoSuchParameterException;
|
||||
import org.hibernate.procedure.ParameterRegistration;
|
||||
import org.hibernate.procedure.ParameterStrategyException;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.ProcedureOutputs;
|
||||
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
||||
import org.hibernate.procedure.spi.ProcedureCallImplementor;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.query.internal.AbstractProducedQuery;
|
||||
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.ProcedureParameterMetadata;
|
||||
import org.hibernate.query.procedure.internal.ProcedureParameterMetadataImpl;
|
||||
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
|
||||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
import org.hibernate.query.spi.AbstractQuery;
|
||||
import org.hibernate.query.spi.MutableQueryOptions;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
||||
import org.hibernate.result.NoMoreReturnsException;
|
||||
import org.hibernate.result.Output;
|
||||
import org.hibernate.result.ResultSetOutput;
|
||||
import org.hibernate.result.UpdateCountOutput;
|
||||
import org.hibernate.result.spi.ResultContext;
|
||||
import org.hibernate.sql.exec.spi.DomainParameterBindingContext;
|
||||
import org.hibernate.sql.results.NoMoreOutputsException;
|
||||
import org.hibernate.sql.results.spi.DomainResultProducer;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -69,26 +76,28 @@ import org.jboss.logging.Logger;
|
|||
*/
|
||||
public class ProcedureCallImpl<R>
|
||||
extends AbstractQuery<R>
|
||||
implements ProcedureCallImplementor<R>, ResultContext {
|
||||
implements ProcedureCallImplementor<R>, ResultContext, DomainParameterBindingContext {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
ProcedureCallImpl.class.getName()
|
||||
);
|
||||
|
||||
private static final NativeSQLQueryReturn[] NO_RETURNS = new NativeSQLQueryReturn[0];
|
||||
|
||||
private final String procedureName;
|
||||
private final NativeSQLQueryReturn[] queryReturns;
|
||||
|
||||
private final boolean globalParameterPassNullsSetting;
|
||||
private FunctionReturnImpl functionReturn;
|
||||
|
||||
private final ProcedureParameterMetadata parameterMetadata;
|
||||
private final ProcedureParameterMetadataImpl parameterMetadata;
|
||||
private final ProcedureParamBindings paramBindings;
|
||||
|
||||
private final List<DomainResultProducer<?>> domainResultProducers;
|
||||
|
||||
private Set<String> synchronizedQuerySpaces;
|
||||
|
||||
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
|
||||
|
||||
private ProcedureOutputsImpl outputs;
|
||||
|
||||
|
||||
/**
|
||||
* The no-returns form.
|
||||
*
|
||||
|
@ -98,14 +107,13 @@ public class ProcedureCallImpl<R>
|
|||
public ProcedureCallImpl(SharedSessionContractImplementor session, String procedureName) {
|
||||
super( session );
|
||||
this.procedureName = procedureName;
|
||||
this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled();
|
||||
|
||||
this.queryReturns = NO_RETURNS;
|
||||
|
||||
this.parameterMetadata = new ProcedureParameterMetadata( this );
|
||||
this.parameterMetadata = new ProcedureParameterMetadataImpl( this );
|
||||
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this );
|
||||
}
|
||||
|
||||
this.synchronizedQuerySpaces = null;
|
||||
this.domainResultProducers = null;
|
||||
}
|
||||
/**
|
||||
* The result Class(es) return form
|
||||
*
|
||||
|
@ -113,39 +121,25 @@ public class ProcedureCallImpl<R>
|
|||
* @param procedureName The name of the procedure to call
|
||||
* @param resultClasses The classes making up the result
|
||||
*/
|
||||
public ProcedureCallImpl(final SharedSessionContractImplementor session, String procedureName, Class... resultClasses) {
|
||||
public ProcedureCallImpl(SharedSessionContractImplementor session, String procedureName, Class... resultClasses) {
|
||||
super( session );
|
||||
|
||||
assert resultClasses != null && resultClasses.length > 0;
|
||||
|
||||
this.procedureName = procedureName;
|
||||
this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled();
|
||||
|
||||
final List<NativeSQLQueryReturn> collectedQueryReturns = new ArrayList<>();
|
||||
final Set<String> collectedQuerySpaces = new HashSet<>();
|
||||
|
||||
Util.resolveResultClasses(
|
||||
new Util.ResultClassesResolutionContext() {
|
||||
@Override
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return session.getFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addQueryReturns(NativeSQLQueryReturn... queryReturns) {
|
||||
Collections.addAll( collectedQueryReturns, queryReturns );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addQuerySpaces(String... spaces) {
|
||||
Collections.addAll( collectedQuerySpaces, spaces );
|
||||
}
|
||||
},
|
||||
resultClasses
|
||||
);
|
||||
|
||||
this.queryReturns = collectedQueryReturns.toArray( new NativeSQLQueryReturn[ collectedQueryReturns.size() ] );
|
||||
this.synchronizedQuerySpaces = collectedQuerySpaces;
|
||||
|
||||
this.parameterMetadata = new ProcedureParameterMetadata( this );
|
||||
this.parameterMetadata = new ProcedureParameterMetadataImpl( this );
|
||||
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this );
|
||||
|
||||
this.domainResultProducers = CollectionHelper.arrayList( resultClasses.length );
|
||||
this.synchronizedQuerySpaces = new HashSet<>();
|
||||
|
||||
Util.resolveResultSetMappingClasses(
|
||||
resultClasses,
|
||||
domainResultProducers::add,
|
||||
synchronizedQuerySpaces::add,
|
||||
getSession().getFactory()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,46 +147,30 @@ public class ProcedureCallImpl<R>
|
|||
*
|
||||
* @param session The session
|
||||
* @param procedureName The name of the procedure to call
|
||||
* @param resultSetMappings The names of the result set mappings making up the result
|
||||
* @param resultSetMappingNames The names of the result set mappings making up the result
|
||||
*/
|
||||
public ProcedureCallImpl(final SharedSessionContractImplementor session, String procedureName, String... resultSetMappings) {
|
||||
public ProcedureCallImpl(
|
||||
final SharedSessionContractImplementor session,
|
||||
String procedureName,
|
||||
String... resultSetMappingNames) {
|
||||
super( session );
|
||||
|
||||
assert resultSetMappingNames != null && resultSetMappingNames.length > 0;
|
||||
|
||||
this.procedureName = procedureName;
|
||||
this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled();
|
||||
|
||||
final List<NativeSQLQueryReturn> collectedQueryReturns = new ArrayList<>();
|
||||
final Set<String> collectedQuerySpaces = new HashSet<>();
|
||||
|
||||
Util.resolveResultSetMappings(
|
||||
new Util.ResultSetMappingResolutionContext() {
|
||||
@Override
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return session.getFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSetMappingDescriptor findResultSetMapping(String name) {
|
||||
return session.getFactory().getNamedQueryRepository().getResultSetMappingDefinition( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addQueryReturns(NativeSQLQueryReturn... queryReturns) {
|
||||
Collections.addAll( collectedQueryReturns, queryReturns );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addQuerySpaces(String... spaces) {
|
||||
Collections.addAll( collectedQuerySpaces, spaces );
|
||||
}
|
||||
},
|
||||
resultSetMappings
|
||||
);
|
||||
|
||||
this.queryReturns = collectedQueryReturns.toArray( new NativeSQLQueryReturn[ collectedQueryReturns.size() ] );
|
||||
this.synchronizedQuerySpaces = collectedQuerySpaces;
|
||||
|
||||
this.parameterMetadata = new ProcedureParameterMetadata( this );
|
||||
this.parameterMetadata = new ProcedureParameterMetadataImpl( this );
|
||||
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this );
|
||||
|
||||
this.domainResultProducers = CollectionHelper.arrayList( resultSetMappingNames.length );
|
||||
this.synchronizedQuerySpaces = new HashSet<>();
|
||||
|
||||
Util.resolveResultSetMappingNames(
|
||||
resultSetMappingNames,
|
||||
domainResultProducers::add,
|
||||
synchronizedQuerySpaces::add,
|
||||
getSession().getFactory()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,52 +179,39 @@ public class ProcedureCallImpl<R>
|
|||
* @param session The session
|
||||
* @param memento The named/stored memento
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
ProcedureCallImpl(SharedSessionContractImplementor session, NamedCallableQueryMemento memento) {
|
||||
super( session );
|
||||
this.procedureName = memento.getCallableName();
|
||||
this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled();
|
||||
|
||||
this.queryReturns = memento.getQueryReturns();
|
||||
this.synchronizedQuerySpaces = Util.copy( memento.getSynchronizedQuerySpaces() );
|
||||
|
||||
this.parameterMetadata = new ProcedureParameterMetadata( this );
|
||||
this.parameterMetadata = new ProcedureParameterMetadataImpl( this, memento );
|
||||
this.paramBindings = new ProcedureParamBindings( parameterMetadata, this );
|
||||
|
||||
for ( NamedCallableQueryMementoImpl.ParameterMemento storedRegistration : memento.getParameterDeclarations() ) {
|
||||
final ProcedureParameterImplementor<?> registration;
|
||||
this.domainResultProducers = new ArrayList<>();
|
||||
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
|
||||
|
||||
if ( StringHelper.isNotEmpty( storedRegistration.getName() ) ) {
|
||||
registration = new ProcedureParameterImpl(
|
||||
this,
|
||||
storedRegistration.getName(),
|
||||
storedRegistration.getMode(),
|
||||
storedRegistration.getType(),
|
||||
storedRegistration.getHibernateType(),
|
||||
storedRegistration.isPassNullsEnabled()
|
||||
);
|
||||
}
|
||||
else {
|
||||
registration = new ProcedureParameterImpl(
|
||||
this,
|
||||
storedRegistration.getPosition(),
|
||||
storedRegistration.getMode(),
|
||||
storedRegistration.getType(),
|
||||
storedRegistration.getHibernateType(),
|
||||
storedRegistration.isPassNullsEnabled()
|
||||
);
|
||||
}
|
||||
Util.resolveResultSetMappings(
|
||||
memento.getResultSetMappingNames(),
|
||||
memento.getResultSetMappingClasses(),
|
||||
domainResultProducers::add,
|
||||
synchronizedQuerySpaces::add,
|
||||
getSession().getFactory()
|
||||
);
|
||||
|
||||
getParameterMetadata().registerParameter( registration );
|
||||
}
|
||||
|
||||
for ( Map.Entry<String, Object> entry : memento.getHintsMap().entrySet() ) {
|
||||
setHint( entry.getKey(), entry.getValue() );
|
||||
}
|
||||
applyOptions( memento );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureParameterMetadata getParameterMetadata() {
|
||||
public String getProcedureName() {
|
||||
return procedureName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableQueryOptions getQueryOptions() {
|
||||
return queryOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureParameterMetadataImpl getParameterMetadata() {
|
||||
return parameterMetadata;
|
||||
}
|
||||
|
||||
|
@ -260,30 +225,85 @@ public class ProcedureCallImpl<R>
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getProcedureName() {
|
||||
return procedureName;
|
||||
public boolean isFunctionCall() {
|
||||
return functionReturn != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql() {
|
||||
return getProcedureName();
|
||||
public ProcedureCall markAsFunctionCall(int sqlType) {
|
||||
functionReturn = new FunctionReturnImpl( this, sqlType );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeSQLQueryReturn[] getQueryReturns() {
|
||||
return queryReturns;
|
||||
public DomainParameterBindingContext getDomainParameterBindingContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// DomainParameterBindingContext
|
||||
|
||||
|
||||
@Override
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return getSession().getFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> getLoadIdentifiers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Parameter registrations
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> registerStoredProcedureParameter(int position, Class type, ParameterMode mode) {
|
||||
getSession().checkOpen( true );
|
||||
|
||||
try {
|
||||
registerParameter( position, type, mode );
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
throw getSession().getExceptionConverter().convert( he );
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getSession().markForRollbackOnly();
|
||||
throw e;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ParameterRegistration<T> registerParameter(int position, Class<T> type, ParameterMode mode) {
|
||||
public ProcedureCallImplementor<R> registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) {
|
||||
getSession().checkOpen( true );
|
||||
try {
|
||||
registerParameter( parameterName, type, mode );
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
throw getSession().getExceptionConverter().convert( he );
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getSession().markForRollbackOnly();
|
||||
throw e;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ProcedureParameter<T> registerParameter(int position, Class<T> javaType, ParameterMode mode) {
|
||||
final ProcedureParameterImpl procedureParameter = new ProcedureParameterImpl(
|
||||
this,
|
||||
position,
|
||||
mode,
|
||||
type,
|
||||
getSession().getFactory().getTypeResolver().heuristicType( type.getName() ),
|
||||
globalParameterPassNullsSetting
|
||||
javaType,
|
||||
getSession().getFactory().getMetamodel().resolveQueryParameterType( javaType )
|
||||
);
|
||||
|
||||
registerParameter( procedureParameter );
|
||||
|
@ -302,20 +322,19 @@ public class ProcedureCallImpl<R>
|
|||
}
|
||||
|
||||
@Override
|
||||
public ParameterRegistrationImplementor getParameterRegistration(int position) {
|
||||
return (ParameterRegistrationImplementor) getParameterMetadata().getQueryParameter( position );
|
||||
public ProcedureParameterImplementor getParameterRegistration(int position) {
|
||||
return getParameterMetadata().getQueryParameter( position );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ParameterRegistration<T> registerParameter(String name, Class<T> type, ParameterMode mode) {
|
||||
public <T> ProcedureParameterImplementor<T> registerParameter(String name, Class<T> type, ParameterMode mode) {
|
||||
final ProcedureParameterImpl parameter = new ProcedureParameterImpl(
|
||||
this,
|
||||
name,
|
||||
mode,
|
||||
type,
|
||||
getSession().getFactory().getTypeResolver().heuristicType( type.getName() ),
|
||||
globalParameterPassNullsSetting
|
||||
getSession().getFactory().getMetamodel().resolveQueryParameterType( type )
|
||||
);
|
||||
|
||||
registerParameter( parameter );
|
||||
|
@ -331,14 +350,14 @@ public class ProcedureCallImpl<R>
|
|||
}
|
||||
|
||||
@Override
|
||||
public ParameterRegistrationImplementor getParameterRegistration(String name) {
|
||||
public ProcedureParameterImplementor getParameterRegistration(String name) {
|
||||
return getParameterMetadata().getQueryParameter( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List getRegisteredParameters() {
|
||||
return new ArrayList( getParameterMetadata().collectAllParameters() );
|
||||
return new ArrayList( getParameterMetadata().getRegistrations() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -382,13 +401,13 @@ public class ProcedureCallImpl<R>
|
|||
// prepare parameters
|
||||
|
||||
getParameterMetadata().visitRegistrations(
|
||||
new Consumer<QueryParameter>() {
|
||||
new Consumer<QueryParameter<?>>() {
|
||||
int i = 1;
|
||||
|
||||
@Override
|
||||
public void accept(QueryParameter queryParameter) {
|
||||
try {
|
||||
final ParameterRegistrationImplementor registration = (ParameterRegistrationImplementor) queryParameter;
|
||||
final ProcedureParameterImplementor registration = (ProcedureParameterImplementor) queryParameter;
|
||||
registration.prepare( statement, i );
|
||||
if ( registration.getMode() == ParameterMode.REF_CURSOR ) {
|
||||
i++;
|
||||
|
@ -416,26 +435,6 @@ public class ProcedureCallImpl<R>
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getReturnAliases() {
|
||||
throw new UnsupportedOperationException( "Procedure/function calls do not support returning aliases" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getReturnTypes() {
|
||||
throw new UnsupportedOperationException( "Procedure/function calls do not support returning 'return types'" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureCallImplementor<R> setEntity(int position, Object val) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureCallImplementor<R> setEntity(String name, Object val) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this form instead of {@link #getSynchronizedQuerySpaces()} when you want to make sure the
|
||||
* underlying Set is instantiated (aka, on add)
|
||||
|
@ -451,7 +450,6 @@ public class ProcedureCallImpl<R>
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<String> getSynchronizedQuerySpaces() {
|
||||
if ( synchronizedQuerySpaces == null ) {
|
||||
return Collections.emptySet();
|
||||
|
@ -484,140 +482,121 @@ public class ProcedureCallImpl<R>
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNativeQuery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryParameters getQueryParameters() {
|
||||
final QueryParameters qp = super.getQueryParameters();
|
||||
// both of these are for documentation purposes, they are actually handled directly...
|
||||
qp.setAutoDiscoverScalarTypes( true );
|
||||
qp.setCallable( true );
|
||||
return qp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects any parameter registrations which indicate a REF_CURSOR parameter type/mode.
|
||||
*
|
||||
* @return The collected REF_CURSOR type parameters.
|
||||
*/
|
||||
public ParameterRegistrationImplementor[] collectRefCursorParameters() {
|
||||
final List<ParameterRegistrationImplementor> refCursorParams = new ArrayList<>();
|
||||
public ProcedureParameterImplementor[] collectRefCursorParameters() {
|
||||
final List<ProcedureParameterImplementor> refCursorParams = new ArrayList<>();
|
||||
|
||||
getParameterMetadata().visitRegistrations(
|
||||
queryParameter -> {
|
||||
final ParameterRegistrationImplementor registration = (ParameterRegistrationImplementor) queryParameter;
|
||||
final ProcedureParameterImplementor registration = (ProcedureParameterImplementor) queryParameter;
|
||||
if ( registration.getMode() == ParameterMode.REF_CURSOR ) {
|
||||
refCursorParams.add( registration );
|
||||
}
|
||||
}
|
||||
);
|
||||
return refCursorParams.toArray( new ParameterRegistrationImplementor[refCursorParams.size()] );
|
||||
return refCursorParams.toArray( new ProcedureParameterImplementor[0] );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedCallableQueryMemento extractMemento(Map<String, Object> hints) {
|
||||
public NamedCallableQueryMemento toMemento(String name) {
|
||||
return new NamedCallableQueryMementoImpl(
|
||||
name,
|
||||
procedureName,
|
||||
Util.copy( queryReturns ),
|
||||
getParameterMetadata().getParameterStrategy(),
|
||||
toParameterMementos( getParameterMetadata() ),
|
||||
Util.copy( synchronizedQuerySpaces ),
|
||||
Util.copy( hints )
|
||||
getParameterStrategy(),
|
||||
toParameterMementos( parameterMetadata ),
|
||||
// todo (6.0) : result-set-mapping names
|
||||
null,
|
||||
// todo (6.0) : result-set-mapping class names
|
||||
null,
|
||||
getSynchronizedQuerySpaces(),
|
||||
isCacheable(),
|
||||
getCacheRegion(),
|
||||
getCacheMode(),
|
||||
getHibernateFlushMode(),
|
||||
isReadOnly(),
|
||||
getTimeout(),
|
||||
getFetchSize(),
|
||||
getComment(),
|
||||
getHints()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedCallableQueryMemento extractMemento() {
|
||||
return new NamedCallableQueryMementoImpl(
|
||||
procedureName,
|
||||
Util.copy( queryReturns ),
|
||||
getParameterMetadata().getParameterStrategy(),
|
||||
toParameterMementos( getParameterMetadata() ),
|
||||
Util.copy( synchronizedQuerySpaces ),
|
||||
Util.copy( getHints() )
|
||||
);
|
||||
}
|
||||
|
||||
private static List<NamedCallableQueryMementoImpl.ParameterMemento> toParameterMementos(ProcedureParameterMetadata parameterMetadata) {
|
||||
private static List<NamedCallableQueryMementoImpl.ParameterMemento> toParameterMementos(
|
||||
ProcedureParameterMetadataImpl parameterMetadata) {
|
||||
if ( parameterMetadata.getParameterStrategy() == ParameterStrategy.UNKNOWN ) {
|
||||
// none...
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<NamedCallableQueryMementoImpl.ParameterMemento> copy = new ArrayList<>();
|
||||
final List<NamedCallableQueryMementoImpl.ParameterMemento> mementos = new ArrayList<>();
|
||||
|
||||
parameterMetadata.visitRegistrations(
|
||||
queryParameter -> {
|
||||
final ParameterRegistrationImplementor registration = (ParameterRegistrationImplementor) queryParameter;
|
||||
copy.add( NamedCallableQueryMementoImpl.ParameterMemento.fromRegistration( registration ) );
|
||||
final ProcedureParameterImplementor procedureParameter = (ProcedureParameterImplementor) queryParameter;
|
||||
mementos.add(
|
||||
new NamedCallableQueryMementoImpl.ParameterMementoImpl(
|
||||
procedureParameter.getPosition(),
|
||||
procedureParameter.getName(),
|
||||
procedureParameter.getMode(),
|
||||
procedureParameter.getParameterType(),
|
||||
procedureParameter.getHibernateType()
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return copy;
|
||||
return mementos;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canApplyAliasSpecificLockModes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verifySettingLockMode() {
|
||||
throw new IllegalStateException( "Illegal attempt to set lock mode on a ProcedureCall / StoredProcedureQuery" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verifySettingAliasSpecificLockModes() {
|
||||
throw new IllegalStateException( "Illegal attempt to set lock mode on a ProcedureCall / StoredProcedureQuery" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyEntityGraphQueryHint(String hintName, RootGraphImplementor entityGraph) {
|
||||
throw new IllegalStateException( "EntityGraph hints are not supported for ProcedureCall/StoredProcedureQuery" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<R> applyGraph(RootGraph<?> graph, GraphSemantic semantic) {
|
||||
throw new IllegalStateException( "EntityGraph hints are not supported for ProcedureCall/StoredProcedureQuery" );
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// JPA StoredProcedureQuery impl
|
||||
// outputs
|
||||
|
||||
private ProcedureOutputs procedureResult;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> registerStoredProcedureParameter(int position, Class type, ParameterMode mode) {
|
||||
getProducer().checkOpen( true );
|
||||
|
||||
try {
|
||||
registerParameter( position, type, mode );
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
throw getExceptionConverter().convert( he );
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getProducer().markForRollbackOnly();
|
||||
throw e;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) {
|
||||
getProducer().checkOpen( true );
|
||||
try {
|
||||
registerParameter( parameterName, type, mode );
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
throw getExceptionConverter().convert( he );
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getProducer().markForRollbackOnly();
|
||||
throw e;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// outputs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
public boolean execute() {
|
||||
try {
|
||||
final Output rtn = outputs().getCurrent();
|
||||
return rtn != null && ResultSetOutput.class.isInstance( rtn );
|
||||
return ResultSetOutput.class.isInstance( rtn );
|
||||
}
|
||||
catch (NoMoreReturnsException e) {
|
||||
catch (NoMoreOutputsException e) {
|
||||
return false;
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
throw getExceptionConverter().convert( he );
|
||||
throw getSession().getExceptionConverter().convert( he );
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getProducer().markForRollbackOnly();
|
||||
getSession().markForRollbackOnly();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -630,9 +609,10 @@ public class ProcedureCallImpl<R>
|
|||
}
|
||||
|
||||
@Override
|
||||
public int executeUpdate() {
|
||||
getSession().checkTransactionNeededForUpdateOperation(
|
||||
"javax.persistence.Query.executeUpdate requires active transaction" );
|
||||
protected int doExecuteUpdate() {
|
||||
if ( ! getSession().isTransactionInProgress() ) {
|
||||
throw new TransactionRequiredException( "javax.persistence.Query.executeUpdate requires active transaction" );
|
||||
}
|
||||
|
||||
// the expectation is that there is just one Output, of type UpdateCountOutput
|
||||
try {
|
||||
|
@ -691,11 +671,11 @@ public class ProcedureCallImpl<R>
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
catch (NoMoreReturnsException e) {
|
||||
catch (NoMoreOutputsException e) {
|
||||
return -1;
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
throw getExceptionConverter().convert( he );
|
||||
throw getSession().getExceptionConverter().convert( he );
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getSession().markForRollbackOnly();
|
||||
|
@ -703,6 +683,39 @@ public class ProcedureCallImpl<R>
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<R> doList() {
|
||||
if ( getMaxResults() == 0 ) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
try {
|
||||
final Output rtn = outputs().getCurrent();
|
||||
if ( ! ResultSetOutput.class.isInstance( rtn ) ) {
|
||||
throw new IllegalStateException( "Current CallableStatement ou was not a ResultSet, but getResultList was called" );
|
||||
}
|
||||
|
||||
return ( (ResultSetOutput) rtn ).getResultList();
|
||||
}
|
||||
catch (NoMoreOutputsException e) {
|
||||
// todo : the spec is completely silent on these type of edge-case scenarios.
|
||||
// Essentially here we'd have a case where there are no more results (ResultSets nor updateCount) but
|
||||
// getResultList was called.
|
||||
return null;
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
throw getSession().getExceptionConverter().convert( he );
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getSession().markForRollbackOnly();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
|
||||
throw new UnsupportedOperationException( "Query#scroll is not valid for ProcedureCall/StoredProcedureQuery" );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -712,7 +725,7 @@ public class ProcedureCallImpl<R>
|
|||
}
|
||||
try {
|
||||
final Output rtn = outputs().getCurrent();
|
||||
if ( ! ResultSetOutput.class.isInstance( rtn ) ) {
|
||||
if ( !(rtn instanceof ResultSetOutput) ) {
|
||||
throw new IllegalStateException( "Current CallableStatement ou was not a ResultSet, but getResultList was called" );
|
||||
}
|
||||
|
||||
|
@ -725,7 +738,7 @@ public class ProcedureCallImpl<R>
|
|||
return null;
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
throw getExceptionConverter().convert( he );
|
||||
throw getSession().getExceptionConverter().convert( he );
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getSession().markForRollbackOnly();
|
||||
|
@ -762,11 +775,28 @@ public class ProcedureCallImpl<R>
|
|||
if ( cls.isInstance( this ) ) {
|
||||
return (T) this;
|
||||
}
|
||||
else if ( cls.isInstance( outputs ) ) {
|
||||
return (T) outputs();
|
||||
|
||||
if ( cls.isInstance( parameterMetadata ) ) {
|
||||
return (T) parameterMetadata;
|
||||
}
|
||||
|
||||
return super.unwrap( cls );
|
||||
if ( cls.isInstance( paramBindings ) ) {
|
||||
return (T) paramBindings;
|
||||
}
|
||||
|
||||
if ( cls.isInstance( queryOptions ) ) {
|
||||
return (T) queryOptions;
|
||||
}
|
||||
|
||||
if ( cls.isInstance( getSession() ) ) {
|
||||
return (T) getSession();
|
||||
}
|
||||
|
||||
if ( ProcedureOutputs.class.isAssignableFrom( cls ) ) {
|
||||
return (T) getOutputs();
|
||||
}
|
||||
|
||||
throw new PersistenceException( "Unrecognized unwrap type : " + cls.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -797,121 +827,100 @@ public class ProcedureCallImpl<R>
|
|||
|
||||
@Override
|
||||
public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P value) {
|
||||
paramBindings.getBinding( getParameterMetadata().resolve( parameter ) ).setBindValue( value );
|
||||
return this;
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <P> ProcedureCallImplementor<R> setParameter(Parameter<P> parameter, P value) {
|
||||
paramBindings.getBinding( getParameterMetadata().resolve( parameter ) ).setBindValue( value );
|
||||
return this;
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Object value) {
|
||||
paramBindings.getBinding( getParameterMetadata().getQueryParameter( name ) ).setBindValue( value );
|
||||
return this;
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( name, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Object value) {
|
||||
paramBindings.getBinding( getParameterMetadata().getQueryParameter( position ) ).setBindValue( value );
|
||||
return this;
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( position, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P value, AllowableParameterType type) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P value, Type type) {
|
||||
final QueryParameterBinding<P> binding = paramBindings.getBinding( parameter );
|
||||
binding.setBindValue( value, type );
|
||||
return this;
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Object value, AllowableParameterType type) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( name, value, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Object value, Type type) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( getParameterMetadata().getQueryParameter( name ) );
|
||||
binding.setBindValue( value, type );
|
||||
return this;
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( name, value, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Object value, AllowableParameterType type) {
|
||||
//noinspection unchecked
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( position, value, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Object value, Type type) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( getParameterMetadata().getQueryParameter( position ) );
|
||||
binding.setBindValue( value, type );
|
||||
return this;
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( position, value, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( parameter );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P value, TemporalType temporalPrecision) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, temporalPrecision );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Object value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( getParameterMetadata().getQueryParameter( name ) );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Object value, TemporalType temporalPrecision) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( name, value, temporalPrecision );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Object value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( getParameterMetadata().getQueryParameter( position ) );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Object value, TemporalType temporalPrecision) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(Parameter parameter, Calendar value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( getParameterMetadata().resolve( parameter ) );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public ProcedureCallImplementor<R> setParameter(Parameter parameter, Calendar value, TemporalType temporalPrecision) {
|
||||
//noinspection unchecked
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, temporalPrecision );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(Parameter parameter, Date value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( getParameterMetadata().resolve( parameter ) );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public ProcedureCallImplementor<R> setParameter(Parameter parameter, Date value, TemporalType temporalPrecision) {
|
||||
//noinspection unchecked
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, temporalPrecision );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Calendar value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( name );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Calendar value, TemporalType temporalPrecision) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( name, value, temporalPrecision );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Date value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( name );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public ProcedureCallImplementor<R> setParameter(String name, Date value, TemporalType temporalPrecision) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( name, value, temporalPrecision );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Calendar value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( position );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Calendar value, TemporalType temporalPrecision) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Date value, TemporalType temporalType) {
|
||||
final QueryParameterBinding binding = paramBindings.getBinding( position );
|
||||
binding.setBindValue( value, temporalType );
|
||||
return this;
|
||||
public ProcedureCallImplementor<R> setParameter(int position, Date value, TemporalType temporalPrecision) {
|
||||
return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.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.query.spi.QueryParameterBindingTypeResolver;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link ProcedureParameterBinding} contract.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ProcedureParameterBindingImpl<T>
|
||||
extends QueryParameterBindingImpl<T>
|
||||
implements ProcedureParameterBindingImplementor<T> {
|
||||
public ProcedureParameterBindingImpl(
|
||||
ProcedureParameterImplementor<T> queryParameter,
|
||||
QueryParameterBindingTypeResolver typeResolver) {
|
||||
super( queryParameter, typeResolver, true );
|
||||
}
|
||||
|
||||
public ProcedureParameterBindingImpl(
|
||||
AllowableParameterType<T> bindType,
|
||||
ProcedureParameterImplementor<T> queryParameter,
|
||||
QueryParameterBindingTypeResolver typeResolver) {
|
||||
super( queryParameter, typeResolver, bindType, true );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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 java.util.Objects;
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.query.AbstractQueryParameter;
|
||||
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> implements ProcedureParameterImplementor<T> {
|
||||
private final String name;
|
||||
private final Integer position;
|
||||
|
||||
private final ParameterMode mode;
|
||||
|
||||
private final Class<T> javaType;
|
||||
|
||||
|
||||
public ProcedureParameterImpl(
|
||||
String name,
|
||||
ParameterMode mode,
|
||||
Class<T> javaType,
|
||||
AllowableParameterType<T> hibernateType) {
|
||||
super( false, hibernateType );
|
||||
this.name = name;
|
||||
this.position = null;
|
||||
this.mode = mode;
|
||||
this.javaType = javaType;
|
||||
}
|
||||
|
||||
public ProcedureParameterImpl(
|
||||
Integer position,
|
||||
ParameterMode mode,
|
||||
Class<T> javaType,
|
||||
AllowableParameterType<T> hibernateType) {
|
||||
super( false, hibernateType );
|
||||
this.name = null;
|
||||
this.position = position;
|
||||
this.mode = mode;
|
||||
this.javaType = javaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getParameterType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
public NamedCallableQueryMemento.ParameterMemento toMemento() {
|
||||
return session -> {
|
||||
if ( getName() != null ) {
|
||||
//noinspection unchecked
|
||||
return new ProcedureParameterImpl(
|
||||
getName(),
|
||||
getMode(),
|
||||
javaType,
|
||||
getHibernateType()
|
||||
);
|
||||
}
|
||||
else {
|
||||
//noinspection unchecked
|
||||
return new ProcedureParameterImpl(
|
||||
getPosition(),
|
||||
getMode(),
|
||||
javaType,
|
||||
getHibernateType()
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
ProcedureParameterImpl<?> that = (ProcedureParameterImpl<?>) o;
|
||||
return Objects.equals( name, that.name ) &&
|
||||
Objects.equals( position, that.position ) &&
|
||||
mode == that.mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash( name, position, mode );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.sql.results.internal.ScalarDomainResultImpl;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.spi.DomainResultProducer;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ScalarDomainResultProducer<T> implements DomainResultProducer<T> {
|
||||
private final SqmExpressable<T> expressableType;
|
||||
|
||||
public ScalarDomainResultProducer(SqmExpressable<T> expressableType) {
|
||||
this.expressableType = expressableType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<T> createDomainResult(
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
return new ScalarDomainResultImpl<>( resultVariable, expressableType );
|
||||
}
|
||||
}
|
|
@ -6,18 +6,18 @@
|
|||
*/
|
||||
package org.hibernate.procedure.internal;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.loader.custom.sql.SQLQueryReturnProcessor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.procedure.UnknownSqlResultSetMappingException;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.metamodel.spi.DomainMetamodel;
|
||||
import org.hibernate.query.spi.NamedQueryRepository;
|
||||
import org.hibernate.query.spi.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.spi.ResultSetMapping;
|
||||
import org.hibernate.sql.results.spi.DomainResultProducer;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -32,148 +32,66 @@ public class Util {
|
|||
private Util() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a copy of the given query return array.
|
||||
*
|
||||
* @param queryReturns The returns to copy
|
||||
*
|
||||
* @return The copy
|
||||
*/
|
||||
public static NativeSQLQueryReturn[] copy(NativeSQLQueryReturn[] queryReturns) {
|
||||
if ( queryReturns == null ) {
|
||||
return new NativeSQLQueryReturn[0];
|
||||
public static void resolveResultSetMappings(
|
||||
String[] resultSetMappingNames,
|
||||
Class[] resultSetMappingClasses,
|
||||
Consumer<DomainResultProducer> resultProducerConsumer,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
if ( ! ArrayHelper.isEmpty( resultSetMappingNames ) ) {
|
||||
// cannot specify both
|
||||
if ( ! ArrayHelper.isEmpty( resultSetMappingClasses ) ) {
|
||||
throw new IllegalArgumentException( "Cannot specify both result-set mapping names and classes" );
|
||||
}
|
||||
resolveResultSetMappingNames( resultSetMappingNames, resultProducerConsumer, querySpaceConsumer, sessionFactory );
|
||||
}
|
||||
else if ( ! ArrayHelper.isEmpty( resultSetMappingClasses ) ) {
|
||||
resolveResultSetMappingClasses( resultSetMappingClasses, resultProducerConsumer, querySpaceConsumer, sessionFactory );
|
||||
}
|
||||
|
||||
final NativeSQLQueryReturn[] copy = new NativeSQLQueryReturn[ queryReturns.length ];
|
||||
System.arraycopy( queryReturns, 0, copy, 0, queryReturns.length );
|
||||
return copy;
|
||||
// otherwise, nothing to resolve
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a (shallow) copy of query spaces to be synchronized
|
||||
*
|
||||
* @param synchronizedQuerySpaces The query spaces
|
||||
*
|
||||
* @return The copy
|
||||
*/
|
||||
public static Set<String> copy(Set<String> synchronizedQuerySpaces) {
|
||||
return CollectionHelper.makeCopy( synchronizedQuerySpaces );
|
||||
}
|
||||
public static void resolveResultSetMappingNames(
|
||||
String[] resultSetMappingNames,
|
||||
Consumer<DomainResultProducer> resultProducerConsumer,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final NamedQueryRepository namedQueryRepository = sessionFactory.getQueryEngine().getNamedQueryRepository();
|
||||
|
||||
/**
|
||||
* Make a (shallow) copy of the JPA query hints map
|
||||
*
|
||||
* @param hints The JPA query hints to copy
|
||||
*
|
||||
* @return The copy
|
||||
*/
|
||||
public static Map<String,Object> copy(Map<String, Object> hints) {
|
||||
return CollectionHelper.makeCopy( hints );
|
||||
}
|
||||
|
||||
/**
|
||||
* Context for resolving result-set-mapping definitions
|
||||
*/
|
||||
public static interface ResultSetMappingResolutionContext {
|
||||
/**
|
||||
* Access to the SessionFactory
|
||||
*
|
||||
* @return SessionFactory
|
||||
*/
|
||||
public SessionFactoryImplementor getSessionFactory();
|
||||
|
||||
/**
|
||||
* Locate a ResultSetMappingDefinition by name
|
||||
*
|
||||
* @param name The name of the ResultSetMappingDefinition to locate
|
||||
*
|
||||
* @return The ResultSetMappingDefinition
|
||||
*/
|
||||
public ResultSetMappingDescriptor findResultSetMapping(String name);
|
||||
|
||||
/**
|
||||
* Callback to add query returns indicated by the result set mapping(s)
|
||||
*
|
||||
* @param queryReturns The query returns
|
||||
*/
|
||||
public void addQueryReturns(NativeSQLQueryReturn... queryReturns);
|
||||
|
||||
/**
|
||||
* Callback to add query spaces indicated by the result set mapping(s)
|
||||
*
|
||||
* @param querySpaces The query spaces
|
||||
*/
|
||||
public void addQuerySpaces(String... querySpaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given result set mapping names
|
||||
*
|
||||
* @param context The context for the resolution. See {@link ResultSetMappingResolutionContext}
|
||||
* @param resultSetMappingNames The names of the result-set-mappings to resolve
|
||||
*/
|
||||
public static void resolveResultSetMappings(ResultSetMappingResolutionContext context, String... resultSetMappingNames) {
|
||||
for ( String resultSetMappingName : resultSetMappingNames ) {
|
||||
log.tracef( "Starting attempt resolve named result-set-mapping : %s", resultSetMappingName );
|
||||
final ResultSetMappingDescriptor mapping = context.findResultSetMapping( resultSetMappingName );
|
||||
if ( mapping == null ) {
|
||||
throw new UnknownSqlResultSetMappingException( "Unknown SqlResultSetMapping [" + resultSetMappingName + "]" );
|
||||
}
|
||||
|
||||
log.tracef( "Found result-set-mapping : %s", mapping.traceLoggableFormat() );
|
||||
|
||||
context.addQueryReturns( mapping.getQueryReturns() );
|
||||
|
||||
final SQLQueryReturnProcessor processor =
|
||||
new SQLQueryReturnProcessor( mapping.getQueryReturns(), context.getSessionFactory() );
|
||||
final SQLQueryReturnProcessor.ResultAliasContext processResult = processor.process();
|
||||
context.addQuerySpaces( processResult.collectQuerySpaces() );
|
||||
final NamedResultSetMappingMemento memento = namedQueryRepository.getResultSetMappingMemento( resultSetMappingName );
|
||||
final ResultSetMapping resultSetMapping = memento.toResultSetMapping();
|
||||
resultProducerConsumer.accept( resultSetMapping );
|
||||
// todo (6.0) : determine query spaces - maybe passing the consumer to `NamedResultSetMappingMemento#toResultSetMapping`?
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Context for resolving result-class definitions
|
||||
*/
|
||||
public static interface ResultClassesResolutionContext {
|
||||
/**
|
||||
* Access to the SessionFactory
|
||||
*
|
||||
* @return SessionFactory
|
||||
*/
|
||||
public SessionFactoryImplementor getSessionFactory();
|
||||
/**
|
||||
* Callback to add query returns indicated by the result set mapping(s)
|
||||
*
|
||||
* @param queryReturns The query returns
|
||||
*/
|
||||
public void addQueryReturns(NativeSQLQueryReturn... queryReturns);
|
||||
public static void resolveResultSetMappingClasses(
|
||||
Class[] resultSetMappingClasses,
|
||||
Consumer<DomainResultProducer> resultProducerConsumer,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
|
||||
/**
|
||||
* Callback to add query spaces indicated by the result set mapping(s)
|
||||
*
|
||||
* @param querySpaces The query spaces
|
||||
*/
|
||||
public void addQuerySpaces(String... querySpaces);
|
||||
}
|
||||
final DomainMetamodel domainModel = sessionFactory.getDomainModel();
|
||||
final TypeConfiguration typeConfiguration = domainModel.getTypeConfiguration();
|
||||
|
||||
/**
|
||||
* Resolve the given result classes
|
||||
*
|
||||
* @param context The context for the resolution. See {@link ResultSetMappingResolutionContext}
|
||||
* @param resultClasses The Classes to which the results should be mapped
|
||||
*/
|
||||
public static void resolveResultClasses(ResultClassesResolutionContext context, Class... resultClasses) {
|
||||
int i = 0;
|
||||
for ( Class resultClass : resultClasses ) {
|
||||
context.addQueryReturns(
|
||||
new NativeSQLQueryRootReturn( "alias" + (++i), resultClass.getName(), LockMode.READ )
|
||||
);
|
||||
try {
|
||||
final EntityPersister persister = context.getSessionFactory().getEntityPersister( resultClass.getName() );
|
||||
context.addQuerySpaces( (String[]) persister.getQuerySpaces() );
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
for ( Class resultSetMappingClass : resultSetMappingClasses ) {
|
||||
final BasicType basicType = typeConfiguration.getBasicTypeForJavaType( resultSetMappingClass );
|
||||
if ( basicType != null ) {
|
||||
//noinspection unchecked
|
||||
resultProducerConsumer.accept( new ScalarDomainResultProducer<>( basicType ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
// final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( resultSetMappingClass );
|
||||
// if ( entityDescriptor != null ) {
|
||||
// resultProducerConsumer.accept( new Entity );
|
||||
// for ( String querySpace : entityDescriptor.getSynchronizedQuerySpaces() ) {
|
||||
// querySpaceConsumer.accept( querySpace );
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,44 +7,27 @@
|
|||
package org.hibernate.procedure.spi;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.procedure.internal.FunctionReturnImpl;
|
||||
import org.hibernate.query.procedure.internal.ProcedureParamBindings;
|
||||
import org.hibernate.query.procedure.internal.ProcedureParameterMetadata;
|
||||
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CallableStatementSupport {
|
||||
default String renderCallableStatement(
|
||||
String name,
|
||||
ParameterStrategy parameterStrategy,
|
||||
List<ParameterRegistrationImplementor<?>> parameterRegistrations,
|
||||
SharedSessionContractImplementor session) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Legacy #renderCallableStatement called but implementation does not support that call."
|
||||
);
|
||||
}
|
||||
|
||||
default String renderCallableStatement(
|
||||
JdbcCall interpretCall(
|
||||
String procedureName,
|
||||
ProcedureParameterMetadata parameterMetadata,
|
||||
FunctionReturnImpl functionReturn,
|
||||
ParameterMetadataImplementor parameterMetadata,
|
||||
ProcedureParamBindings paramBindings,
|
||||
SharedSessionContractImplementor session) {
|
||||
return renderCallableStatement(
|
||||
procedureName,
|
||||
parameterMetadata.getParameterStrategy(),
|
||||
new ArrayList( parameterMetadata.collectAllParameters() ),
|
||||
session
|
||||
);
|
||||
}
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
void registerParameters(
|
||||
String procedureName,
|
||||
CallableStatement statement,
|
||||
ParameterStrategy parameterStrategy,
|
||||
List<ParameterRegistrationImplementor<?>> parameterRegistrations,
|
||||
ParameterMetadataImplementor parameterMetadata,
|
||||
SharedSessionContractImplementor session);
|
||||
}
|
||||
|
|
|
@ -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.procedure.spi;
|
||||
|
||||
import org.hibernate.procedure.FunctionReturn;
|
||||
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface FunctionReturnImplementor extends FunctionReturn, ProcedureParameterImplementor {
|
||||
}
|
|
@ -6,11 +6,15 @@
|
|||
*/
|
||||
package org.hibernate.procedure.spi;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -25,6 +29,8 @@ public interface NamedCallableQueryMemento extends NamedQueryMemento {
|
|||
*/
|
||||
String getCallableName();
|
||||
|
||||
List<ParameterMemento> getParameterMementos();
|
||||
|
||||
/**
|
||||
* Convert the memento back into an executable (connected) form.
|
||||
*
|
||||
|
@ -47,6 +53,14 @@ public interface NamedCallableQueryMemento extends NamedQueryMemento {
|
|||
return makeProcedureCall( (SharedSessionContractImplementor) session );
|
||||
}
|
||||
|
||||
ParameterStrategy getParameterStrategy();
|
||||
|
||||
String[] getResultSetMappingNames();
|
||||
|
||||
Class[] getResultSetMappingClasses();
|
||||
|
||||
Set<String> getQuerySpaces();
|
||||
|
||||
/**
|
||||
* Convert the memento back into an executable (connected) form.
|
||||
*
|
||||
|
@ -57,6 +71,6 @@ public interface NamedCallableQueryMemento extends NamedQueryMemento {
|
|||
ProcedureCall makeProcedureCall(SharedSessionContractImplementor session);
|
||||
|
||||
interface ParameterMemento {
|
||||
ParameterRegistrationImplementor resolve(SharedSessionContractImplementor session);
|
||||
ProcedureParameterImplementor resolve(SharedSessionContractImplementor session);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,69 +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.spi;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.procedure.ParameterRegistration;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Additional internal contract for ParameterRegistration
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ParameterRegistrationImplementor<T> extends ParameterRegistration<T> {
|
||||
/**
|
||||
* Prepare for execution.
|
||||
*
|
||||
* @param statement The statement about to be executed
|
||||
* @param i The parameter index for this registration (used for positional)
|
||||
*
|
||||
* @throws SQLException Indicates a problem accessing the statement object
|
||||
*/
|
||||
void prepare(CallableStatement statement, int i) throws SQLException;
|
||||
|
||||
/**
|
||||
* Access to the Hibernate type for this parameter registration
|
||||
*
|
||||
* @return The Hibernate Type
|
||||
*/
|
||||
@Override
|
||||
Type getHibernateType();
|
||||
|
||||
/**
|
||||
* If no value is bound for this parameter registration, is the passing of NULL
|
||||
* to the JDBC CallableStatement for that parameter enabled? This effectively controls
|
||||
* whether default values for the argument as defined in the database are applied or not.
|
||||
*
|
||||
* @return {@code true} indicates that NULL will be passed to the JDBC driver, effectively disabling
|
||||
* the application of the default argument value defined in the database; {@code false} indicates
|
||||
* that the parameter will simply be ignored, with the assumption that the corresponding argument
|
||||
* defined a default value.
|
||||
*/
|
||||
@Override
|
||||
boolean isPassNullsEnabled();
|
||||
|
||||
/**
|
||||
* Access to the SQL type(s) for this parameter
|
||||
*
|
||||
* @return The SQL types (JDBC type codes)
|
||||
*/
|
||||
int[] getSqlTypes();
|
||||
|
||||
/**
|
||||
* Extract value from the statement after execution (used for OUT/INOUT parameters).
|
||||
*
|
||||
* @param statement The callable statement
|
||||
*
|
||||
* @return The extracted value
|
||||
*/
|
||||
T extract(CallableStatement statement);
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractQueryParameter<T> implements QueryParameterImplementor<T> {
|
||||
private boolean allowMultiValuedBinding;
|
||||
private AllowableParameterType<T> anticipatedType;
|
||||
|
||||
public AbstractQueryParameter(
|
||||
boolean allowMultiValuedBinding,
|
||||
AllowableParameterType<T> anticipatedType) {
|
||||
this.allowMultiValuedBinding = allowMultiValuedBinding;
|
||||
this.anticipatedType = anticipatedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disallowMultiValuedBinding() {
|
||||
QueryLogger.QUERY_LOGGER.debugf( "QueryParameter#disallowMultiValuedBinding() called : %s", this );
|
||||
this.allowMultiValuedBinding = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowsMultiValuedBinding() {
|
||||
return allowMultiValuedBinding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllowableParameterType<T> getHibernateType() {
|
||||
return anticipatedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAnticipatedType(AllowableParameterType type) {
|
||||
//noinspection unchecked
|
||||
this.anticipatedType = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPosition() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getParameterType() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -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.procedure;
|
||||
package org.hibernate.query;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query.hql.spi;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.spi.NameableQuery;
|
||||
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
|
@ -16,7 +15,7 @@ import org.hibernate.query.spi.QueryImplementor;
|
|||
*/
|
||||
public interface HqlQueryImplementor<R> extends QueryImplementor<R>, NameableQuery {
|
||||
@Override
|
||||
NamedHqlQueryMemento toMemento(String name, SessionFactoryImplementor factory);
|
||||
NamedHqlQueryMemento toMemento(String name);
|
||||
|
||||
@Override
|
||||
ParameterMetadataImplementor getParameterMetadata();
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.boot.spi.NamedHqlQueryDefinition;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
|
||||
import org.hibernate.query.spi.AbstractNamedQueryMemento;
|
||||
import org.hibernate.query.spi.NameableQuery;
|
||||
import org.hibernate.query.spi.NamedQueryMemento;
|
||||
|
||||
/**
|
||||
|
@ -52,7 +53,7 @@ public interface NamedHqlQueryMemento extends NamedQueryMemento {
|
|||
* Delegate used in creating named HQL query mementos.
|
||||
*
|
||||
* @see NamedHqlQueryDefinition
|
||||
* @see HqlQueryImplementor#toMemento
|
||||
* @see NameableQuery#toMemento
|
||||
*/
|
||||
class Builder extends AbstractNamedQueryMemento.AbstractBuilder<Builder> {
|
||||
protected String hqlString;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.query.internal;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* QueryParameter implementation.
|
||||
|
@ -17,24 +17,25 @@ import org.hibernate.type.Type;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class QueryParameterImpl<T> implements QueryParameter<T> {
|
||||
private Type expectedType;
|
||||
public abstract class AbstractQueryParameterImpl<T> implements QueryParameter<T> {
|
||||
private AllowableParameterType<T> expectedType;
|
||||
|
||||
public QueryParameterImpl(Type expectedType) {
|
||||
public AbstractQueryParameterImpl(AllowableParameterType<T> expectedType) {
|
||||
this.expectedType = expectedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getHibernateType() {
|
||||
public AllowableParameterType<T> getHibernateType() {
|
||||
return expectedType;
|
||||
}
|
||||
|
||||
public void setHibernateType(Type expectedType) {
|
||||
this.expectedType = expectedType;
|
||||
public void setHibernateType(AllowableParameterType<?> expectedType) {
|
||||
//noinspection unchecked
|
||||
this.expectedType = (AllowableParameterType) expectedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getParameterType() {
|
||||
return expectedType == null ? null : expectedType.getReturnedClass();
|
||||
return expectedType == null ? null : expectedType.getJavaType();
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ import org.hibernate.type.Type;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QueryParameterNamedImpl<T> extends QueryParameterImpl<T> implements QueryParameter<T> {
|
||||
public class QueryParameterNamedImpl<T> extends AbstractQueryParameterImpl<T> implements QueryParameter<T> {
|
||||
private final String name;
|
||||
private final int[] sourceLocations;
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.query.procedure;
|
|||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
|
||||
/**
|
||||
|
@ -33,8 +32,6 @@ public interface ProcedureParameter<T> extends QueryParameter<T> {
|
|||
* @return {@code true} here indicates that NULL should be passed; {@code false} indicates
|
||||
* that it is ignored.
|
||||
*
|
||||
* @see ParameterRegistrationImplementor#isPassNullsEnabled()
|
||||
*
|
||||
* @deprecated (since 6.0) : Passing null or not is now triggered by whether
|
||||
* setting the parameter was called at all. In other words a distinction is
|
||||
* made between calling `setParameter` passing {@code null} versus not calling
|
||||
|
@ -42,18 +39,19 @@ public interface ProcedureParameter<T> extends QueryParameter<T> {
|
|||
* the second we do not pass {@code null}.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isPassNullsEnabled();
|
||||
default boolean isPassNullsEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls how unbound values for this IN/INOUT parameter registration will be handled prior to
|
||||
* execution. For details see {@link org.hibernate.procedure.ParameterRegistration#enablePassingNulls}
|
||||
* execution.
|
||||
*
|
||||
* @param enabled {@code true} indicates that the NULL should be passed; {@code false} indicates it should not.
|
||||
*
|
||||
* @see org.hibernate.procedure.ParameterRegistration#enablePassingNulls
|
||||
*
|
||||
* @deprecated (since 6.0) : see {@link #isPassNullsEnabled}
|
||||
*/
|
||||
@Deprecated
|
||||
void enablePassingNulls(boolean enabled);
|
||||
default void enablePassingNulls(boolean enabled) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.query.procedure;
|
|||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
|
||||
/**
|
||||
* Describes an input value binding for any IN/INOUT parameters.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ProcedureParameterBinding<T> extends QueryParameterBinding<T> {
|
||||
|
|
|
@ -10,35 +10,31 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.procedure.ParameterBind;
|
||||
import org.hibernate.procedure.internal.ParameterBindImpl;
|
||||
import org.hibernate.procedure.internal.ProcedureCallImpl;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.query.procedure.ProcedureParameterBinding;
|
||||
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
|
||||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
import org.hibernate.query.spi.QueryParameterListBinding;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ProcedureParamBindings implements QueryParameterBindings {
|
||||
private final ProcedureParameterMetadata parameterMetadata;
|
||||
private final ProcedureParameterMetadataImpl parameterMetadata;
|
||||
private final ProcedureCallImpl procedureCall;
|
||||
|
||||
private final Map<ProcedureParameterImplementor, ParameterBind> bindingMap = new HashMap<>();
|
||||
private final Map<ProcedureParameterImplementor<?>, ProcedureParameterBinding<?>> bindingMap = new HashMap<>();
|
||||
|
||||
public ProcedureParamBindings(
|
||||
ProcedureParameterMetadata parameterMetadata,
|
||||
ProcedureParameterMetadataImpl parameterMetadata,
|
||||
ProcedureCallImpl procedureCall) {
|
||||
this.parameterMetadata = parameterMetadata;
|
||||
this.procedureCall = procedureCall;
|
||||
}
|
||||
|
||||
public ProcedureParameterMetadata getParameterMetadata() {
|
||||
public ProcedureParameterMetadataImpl getParameterMetadata() {
|
||||
return parameterMetadata;
|
||||
}
|
||||
|
||||
|
@ -47,14 +43,13 @@ public class ProcedureParamBindings implements QueryParameterBindings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isBound(QueryParameter parameter) {
|
||||
return getBinding( parameter ).isBound();
|
||||
public QueryParameterBinding<?> getBinding(QueryParameterImplementor<?> parameter) {
|
||||
return getBinding( parameterMetadata.resolve( parameter ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryParameterBinding<T> getBinding(QueryParameter<T> parameter) {
|
||||
final ProcedureParameterImplementor<T> procParam = parameterMetadata.resolve( parameter );
|
||||
ParameterBind binding = bindingMap.get( procParam );
|
||||
public QueryParameterBinding<?> getBinding(ProcedureParameterImplementor parameter) {
|
||||
final ProcedureParameterImplementor procParam = parameterMetadata.resolve( parameter );
|
||||
ProcedureParameterBinding binding = bindingMap.get( procParam );
|
||||
|
||||
if ( binding == null ) {
|
||||
if ( ! parameterMetadata.containsReference( parameter ) ) {
|
||||
|
@ -69,12 +64,12 @@ public class ProcedureParamBindings implements QueryParameterBindings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryParameterBinding<T> getBinding(String name) {
|
||||
public ProcedureParameterBinding<?> getBinding(String name) {
|
||||
return getBinding( parameterMetadata.getQueryParameter( name ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryParameterBinding<T> getBinding(int position) {
|
||||
public ProcedureParameterBinding getBinding(int position) {
|
||||
return getBinding( parameterMetadata.getQueryParameter( position ) );
|
||||
}
|
||||
|
||||
|
@ -94,42 +89,4 @@ public class ProcedureParamBindings implements QueryParameterBindings {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String expandListValuedParameters(String queryString, SharedSessionContractImplementor producer) {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryParameterListBinding<T> getQueryParameterListBinding(QueryParameter<T> parameter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryParameterListBinding<T> getQueryParameterListBinding(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryParameterListBinding<T> getQueryParameterListBinding(int position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// I think these are not needed for proc call execution
|
||||
|
||||
@Override
|
||||
public Type[] collectPositionalBindTypes() {
|
||||
return new Type[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] collectPositionalBindValues() {
|
||||
return new Object[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, TypedValue> collectNamedParameterBindings() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,24 +8,20 @@ package org.hibernate.query.procedure.internal;
|
|||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Calendar;
|
||||
import javax.persistence.ParameterMode;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
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.procedure.ParameterBind;
|
||||
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.ParameterRegistration;
|
||||
import org.hibernate.procedure.internal.ProcedureCallImpl;
|
||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
||||
import org.hibernate.query.internal.QueryParameterImpl;
|
||||
import org.hibernate.query.internal.AbstractQueryParameterImpl;
|
||||
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
|
||||
import org.hibernate.type.CalendarDateType;
|
||||
import org.hibernate.type.CalendarTimeType;
|
||||
import org.hibernate.type.CalendarType;
|
||||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
import org.hibernate.type.ProcedureParameterExtractionAware;
|
||||
import org.hibernate.type.ProcedureParameterNamedBinder;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -36,8 +32,8 @@ import org.jboss.logging.Logger;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ProcedureParameterImpl<T>
|
||||
extends QueryParameterImpl<T>
|
||||
implements ProcedureParameterImplementor<T>, ParameterRegistration<T> {
|
||||
extends AbstractQueryParameterImpl<T>
|
||||
implements ProcedureParameterImplementor<T> {
|
||||
private static final Logger log = Logger.getLogger( ProcedureParameterImpl.class );
|
||||
|
||||
private final ProcedureCallImpl procedureCall;
|
||||
|
@ -46,9 +42,6 @@ public class ProcedureParameterImpl<T>
|
|||
private final ParameterMode mode;
|
||||
private final Class<T> javaType;
|
||||
|
||||
private int[] sqlTypes;
|
||||
private boolean passNullsEnabled;
|
||||
|
||||
// in-flight state needed between prepare and extract
|
||||
private int startIndex;
|
||||
|
||||
|
@ -57,15 +50,13 @@ public class ProcedureParameterImpl<T>
|
|||
String name,
|
||||
ParameterMode mode,
|
||||
Class<T> javaType,
|
||||
Type hibernateType,
|
||||
boolean initialPassNullsSetting) {
|
||||
AllowableParameterType<T> hibernateType) {
|
||||
super( hibernateType );
|
||||
this.procedureCall = procedureCall;
|
||||
this.name = name;
|
||||
this.position = null;
|
||||
this.mode = mode;
|
||||
this.javaType = javaType;
|
||||
this.passNullsEnabled = initialPassNullsSetting;
|
||||
|
||||
setHibernateType( hibernateType );
|
||||
}
|
||||
|
@ -75,15 +66,13 @@ public class ProcedureParameterImpl<T>
|
|||
Integer position,
|
||||
ParameterMode mode,
|
||||
Class<T> javaType,
|
||||
Type hibernateType,
|
||||
boolean initialPassNullsSetting) {
|
||||
AllowableParameterType<T> hibernateType) {
|
||||
super( hibernateType );
|
||||
this.procedureCall = procedureCall;
|
||||
this.name = null;
|
||||
this.position = position;
|
||||
this.mode = mode;
|
||||
this.javaType = javaType;
|
||||
this.passNullsEnabled = initialPassNullsSetting;
|
||||
|
||||
setHibernateType( hibernateType );
|
||||
}
|
||||
|
@ -93,21 +82,6 @@ public class ProcedureParameterImpl<T>
|
|||
return mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPassNullsEnabled() {
|
||||
return passNullsEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enablePassingNulls(boolean enabled) {
|
||||
this.passNullsEnabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSourceLocations() {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -119,74 +93,29 @@ public class ProcedureParameterImpl<T>
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setHibernateType(Type expectedType) {
|
||||
public void setHibernateType(AllowableParameterType<?> expectedType) {
|
||||
super.setHibernateType( expectedType );
|
||||
|
||||
if ( mode == ParameterMode.REF_CURSOR ) {
|
||||
sqlTypes = new int[] { Types.REF_CURSOR };
|
||||
}
|
||||
else {
|
||||
if ( expectedType == null ) {
|
||||
throw new IllegalArgumentException( "Type cannot be null" );
|
||||
}
|
||||
else {
|
||||
sqlTypes = expectedType.sqlTypes( procedureCall.getSession().getFactory() );
|
||||
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 Class<T> getParameterType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterBind<T> getBind() {
|
||||
return (ParameterBind<T>) procedureCall.getQueryParameterBindings().getBinding( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void bindValue(Object value) {
|
||||
getBind().setBindValue( (T) value );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void bindValue(Object value, TemporalType explicitTemporalType) {
|
||||
getBind().setBindValue( (T) value, explicitTemporalType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(CallableStatement statement, int startIndex) throws SQLException {
|
||||
// initially set up the Type we will use for binding as the explicit type.
|
||||
Type typeToUse = getHibernateType();
|
||||
int[] sqlTypesToUse = sqlTypes;
|
||||
final QueryParameterBinding<?> binding = procedureCall.getQueryParameterBindings().getBinding( this );
|
||||
|
||||
final ParameterBind bind = getBind();
|
||||
// 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 ( bind != null && bind.getExplicitTemporalType() != null ) {
|
||||
if ( Calendar.class.isInstance( bind.getValue() ) ) {
|
||||
switch ( bind.getExplicitTemporalType() ) {
|
||||
case TIMESTAMP: {
|
||||
typeToUse = CalendarType.INSTANCE;
|
||||
sqlTypesToUse = typeToUse.sqlTypes( procedureCall.getSession().getFactory() );
|
||||
break;
|
||||
}
|
||||
case DATE: {
|
||||
typeToUse = CalendarDateType.INSTANCE;
|
||||
sqlTypesToUse = typeToUse.sqlTypes( procedureCall.getSession().getFactory() );
|
||||
break;
|
||||
}
|
||||
case TIME: {
|
||||
typeToUse = CalendarTimeType.INSTANCE;
|
||||
sqlTypesToUse = typeToUse.sqlTypes( procedureCall.getSession().getFactory() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( binding != null && binding.getExplicitTemporalPrecision() != null ) {
|
||||
typeToUse = ( (AllowableTemporalParameterType) typeToUse ).resolveTemporalPrecision(
|
||||
binding.getExplicitTemporalPrecision(),
|
||||
procedureCall.getSession().getFactory().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
|
||||
this.startIndex = startIndex;
|
||||
|
@ -226,10 +155,10 @@ public class ProcedureParameterImpl<T>
|
|||
}
|
||||
|
||||
if ( mode == ParameterMode.INOUT || mode == ParameterMode.IN ) {
|
||||
if ( bind == null || bind.getValue() == null ) {
|
||||
// the user did not bind a value to the parameter being processed. This is the condition
|
||||
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 bind the NULL value into the statement; 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
|
||||
|
@ -264,13 +193,13 @@ public class ProcedureParameterImpl<T>
|
|||
if ( this.procedureCall.getParameterStrategy() == ParameterStrategy.NAMED && canDoNameParameterBinding( typeToUse ) ) {
|
||||
((ProcedureParameterNamedBinder) typeToUse).nullSafeSet(
|
||||
statement,
|
||||
bind.getValue(),
|
||||
binding.getValue(),
|
||||
this.getName(),
|
||||
procedureCall.getSession()
|
||||
);
|
||||
}
|
||||
else {
|
||||
typeToUse.nullSafeSet( statement, bind.getValue(), startIndex, procedureCall.getSession() );
|
||||
typeToUse.nullSafeSet( statement, binding.getValue(), startIndex, procedureCall.getSession() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -303,16 +232,6 @@ public class ProcedureParameterImpl<T>
|
|||
&& ((ProcedureParameterNamedBinder) hibernateType).canDoSetting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSqlTypes() {
|
||||
if ( mode == ParameterMode.REF_CURSOR ) {
|
||||
// we could use the Types#REF_CURSOR added in Java 8, but that would require requiring Java 8...
|
||||
throw new IllegalStateException( "REF_CURSOR parameters do not have a SQL/JDBC type" );
|
||||
}
|
||||
|
||||
return determineHibernateType().sqlTypes( procedureCall.getSession().getFactory() );
|
||||
}
|
||||
|
||||
private Type determineHibernateType() {
|
||||
final ParameterBind<T> bind = getBind();
|
||||
|
||||
|
|
|
@ -7,37 +7,44 @@
|
|||
package org.hibernate.query.procedure.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.persistence.Parameter;
|
||||
|
||||
import org.hibernate.procedure.internal.ProcedureCallImpl;
|
||||
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
||||
import org.hibernate.query.ParameterMetadata;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.query.procedure.ProcedureParameter;
|
||||
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;
|
||||
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ProcedureParameterMetadata implements ParameterMetadataImplementor {
|
||||
public class ProcedureParameterMetadataImpl implements ParameterMetadataImplementor {
|
||||
private final ProcedureCallImpl procedureCall;
|
||||
private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN;
|
||||
private List<ProcedureParameterImplementor> parameters = new ArrayList<>();
|
||||
|
||||
public ProcedureParameterMetadata(ProcedureCallImpl procedureCall) {
|
||||
private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN;
|
||||
private List<ProcedureParameterImplementor<?>> parameters = new ArrayList<>();
|
||||
|
||||
public ProcedureParameterMetadataImpl(ProcedureCallImpl procedureCall) {
|
||||
this.procedureCall = procedureCall;
|
||||
}
|
||||
|
||||
public <R> ProcedureParameterMetadataImpl(ProcedureCallImpl procedureCall, NamedCallableQueryMemento memento) {
|
||||
this( procedureCall );
|
||||
memento.getParameterMementos().forEach(
|
||||
parameterMemento -> registerParameter( parameterMemento.resolve( procedureCall.getSession() ) )
|
||||
);
|
||||
}
|
||||
|
||||
public void registerParameter(ProcedureParameterImplementor parameter) {
|
||||
if ( parameter.getName() != null ) {
|
||||
if ( parameterStrategy == ParameterStrategy.POSITIONAL ) {
|
||||
|
@ -72,24 +79,6 @@ public class ProcedureParameterMetadata implements ParameterMetadataImplementor
|
|||
return parameterStrategy == ParameterStrategy.POSITIONAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<QueryParameter<?>> collectAllParameters() {
|
||||
final Set<QueryParameter<?>> rtn = new LinkedHashSet<>();
|
||||
for ( ProcedureParameter parameter : parameters ) {
|
||||
rtn.add( parameter );
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Parameter<?>> collectAllParametersJpa() {
|
||||
final Set<Parameter<?>> rtn = new LinkedHashSet<>();
|
||||
for ( ProcedureParameter parameter : parameters ) {
|
||||
rtn.add( parameter );
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getNamedParameterNames() {
|
||||
if ( !hasNamedParameters() ) {
|
||||
|
@ -105,67 +94,6 @@ public class ProcedureParameterMetadata implements ParameterMetadataImplementor
|
|||
return rtn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPositionalParameterCount() {
|
||||
return hasPositionalParameters() ? parameters.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ParameterRegistrationImplementor<T> getQueryParameter(String name) {
|
||||
assert name != null;
|
||||
|
||||
if ( hasNamedParameters() ) {
|
||||
for ( ParameterRegistrationImplementor parameter : parameters ) {
|
||||
if ( name.equals( parameter.getName() ) ) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException( "Named parameter [" + name + "] is not registered with this procedure call" );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ParameterRegistrationImplementor<T> getQueryParameter(Integer position) {
|
||||
assert position != null;
|
||||
|
||||
if ( hasPositionalParameters() ) {
|
||||
for ( ParameterRegistrationImplementor parameter : parameters ) {
|
||||
if ( parameter.getPosition() != null && position.intValue() == parameter.getPosition() ) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException( "Positional parameter [" + position + "] is not registered with this procedure call" );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ProcedureParameterImplementor<T> resolve(Parameter<T> param) {
|
||||
if ( ProcedureParameterImplementor.class.isInstance( param ) ) {
|
||||
for ( ProcedureParameterImplementor parameter : parameters ) {
|
||||
if ( parameter == param ) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException( "Could not resolve javax.persistence.Parameter to org.hibernate.query.QueryParameter" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QueryParameter> getPositionalParameters() {
|
||||
return parameters.stream().filter( p -> p.getPosition() != null ).collect( Collectors.toList() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QueryParameter> getNamedParameters() {
|
||||
return parameters.stream().filter( p -> p.getPosition() == null ).collect( Collectors.toList() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParameterCount() {
|
||||
return parameters.size();
|
||||
|
@ -182,10 +110,78 @@ public class ProcedureParameterMetadata implements ParameterMetadataImplementor
|
|||
}
|
||||
|
||||
@Override
|
||||
public void visitRegistrations(Consumer<QueryParameter> action) {
|
||||
for ( ProcedureParameterImplementor parameter : parameters ) {
|
||||
action.accept( parameter );
|
||||
public void collectAllParameters(ParameterCollector collector) {
|
||||
parameters.forEach( collector::collect );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnyMatching(Predicate<QueryParameterImplementor<?>> filter) {
|
||||
if ( parameters.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( ProcedureParameterImplementor parameter : parameters ) {
|
||||
if ( filter.test( parameter ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureParameterImplementor<?> getQueryParameter(String name) {
|
||||
for ( ProcedureParameterImplementor parameter : parameters ) {
|
||||
if ( name.equals( parameter.getName() ) ) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureParameterImplementor<?> getQueryParameter(int positionLabel) {
|
||||
for ( ProcedureParameterImplementor parameter : parameters ) {
|
||||
if ( parameter.getName() == null && positionLabel == parameter.getPosition() ) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcedureParameterImplementor<?> resolve(Parameter param) {
|
||||
if ( param instanceof ProcedureParameterImplementor ) {
|
||||
return (ProcedureParameterImplementor) param;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends QueryParameter<?>> getRegistrations() {
|
||||
//noinspection unchecked
|
||||
return (Set) parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRegistrations(Consumer<? extends QueryParameter<?>> action) {
|
||||
//noinspection unchecked
|
||||
parameters.forEach( (Consumer) action );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> getOrdinalParameterLabels() {
|
||||
final HashSet<Integer> labels = new HashSet<>();
|
||||
visitRegistrations(
|
||||
p -> {
|
||||
if ( p.getPosition() != null ) {
|
||||
labels.add( p.getPosition() );
|
||||
}
|
||||
}
|
||||
);
|
||||
return labels;
|
||||
}
|
||||
}
|
|
@ -6,9 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.query.procedure.spi;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
|
||||
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
|
||||
|
@ -16,5 +19,11 @@ import org.hibernate.query.procedure.ProcedureParameter;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface ProcedureParameterImplementor<T> extends ProcedureParameter<T>, ParameterRegistrationImplementor<T> {
|
||||
public interface ProcedureParameterImplementor<T> extends ProcedureParameter<T>, QueryParameterImplementor<T> {
|
||||
void prepare(CallableStatement statement, int startIndex) throws SQLException;
|
||||
|
||||
@Override
|
||||
default boolean allowsMultiValuedBinding() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,7 +225,9 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
public QueryImplementor setFlushMode(FlushModeType flushModeType) {
|
||||
setHibernateFlushMode( FlushModeTypeHelper.getFlushMode( flushModeType ) );
|
||||
return this;
|
||||
} @Override
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheMode getCacheMode() {
|
||||
return getQueryOptions().getCacheMode();
|
||||
}
|
||||
|
|
|
@ -7,15 +7,17 @@
|
|||
package org.hibernate.query.spi;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
/**
|
||||
* Contract for Query impls that can be converted to named queries and
|
||||
* Contract for Query impls that can be converted to a named query memento to be
|
||||
* stored in the {@link org.hibernate.query.spi.NamedQueryRepository}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface NameableQuery {
|
||||
NamedQueryMemento toMemento(String name, SessionFactoryImplementor factory);
|
||||
/**
|
||||
* Convert the query into the memento
|
||||
*/
|
||||
NamedQueryMemento toMemento(String name);
|
||||
}
|
||||
|
|
|
@ -40,10 +40,14 @@ public interface QueryParameterBinding<T> {
|
|||
*/
|
||||
AllowableParameterType<T> getBindType();
|
||||
|
||||
/**
|
||||
* If the parameter represents a temporal type, return the explicitly
|
||||
* specified precision - if one.
|
||||
*/
|
||||
TemporalType getExplicitTemporalPrecision();
|
||||
|
||||
/**
|
||||
* Sets the parameter binding value. The inherent parameter type (if known) is assumed
|
||||
*
|
||||
* @param value The bind value
|
||||
*/
|
||||
void setBindValue(T value);
|
||||
|
||||
|
|
|
@ -475,7 +475,7 @@ public class QuerySqmImpl<R>
|
|||
}
|
||||
|
||||
@Override
|
||||
public NamedHqlQueryMemento toMemento(String name, SessionFactoryImplementor factory) {
|
||||
public NamedHqlQueryMemento toMemento(String name) {
|
||||
return new NamedHqlQueryMementoImpl(
|
||||
name,
|
||||
hqlString,
|
||||
|
|
|
@ -8,20 +8,19 @@ package org.hibernate.result.spi;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.sql.exec.spi.DomainParameterBindingContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ResultContext {
|
||||
SharedSessionContractImplementor getSession();
|
||||
|
||||
Set<String> getSynchronizedQuerySpaces();
|
||||
|
||||
// for now...
|
||||
// see Loader-redesign proposal
|
||||
String getSql();
|
||||
QueryParameters getQueryParameters();
|
||||
NativeSQLQueryReturn[] getQueryReturns();
|
||||
QueryOptions getQueryOptions();
|
||||
|
||||
DomainParameterBindingContext getDomainParameterBindingContext();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NoMoreOutputsException extends HibernateException {
|
||||
public NoMoreOutputsException(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
public NoMoreOutputsException() {
|
||||
super( "Outputs have been exhausted" );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.ConvertibleValueMapping;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.sql.results.spi.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingOptions;
|
||||
import org.hibernate.sql.results.spi.RowProcessingState;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicResultAssembler<J> implements DomainResultAssembler<J> {
|
||||
private final SqmExpressable<J> expressableType;
|
||||
private final BasicValueConverter<J,?> valueConverter;
|
||||
|
||||
public BasicResultAssembler(SqmExpressable<J> expressableType) {
|
||||
this(
|
||||
expressableType,
|
||||
expressableType instanceof ConvertibleValueMapping
|
||||
? ( (ConvertibleValueMapping<J>) expressableType ).getValueConverter()
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
public BasicResultAssembler(SqmExpressable<J> expressableType, BasicValueConverter<J, ?> valueConverter) {
|
||||
this.expressableType = expressableType;
|
||||
this.valueConverter = valueConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object assemble(
|
||||
RowProcessingState rowProcessingState,
|
||||
JdbcValuesSourceProcessingOptions options) {
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<J> getJavaTypeDescriptor() {
|
||||
return expressableType.getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.function.Consumer;
|
||||
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.ConvertibleValueMapping;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.sql.results.spi.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.spi.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.spi.Initializer;
|
||||
import org.hibernate.sql.results.spi.ScalarDomainResult;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ScalarDomainResultImpl<T> implements ScalarDomainResult<T> {
|
||||
private final String resultVariable;
|
||||
private final SqmExpressable expressableType;
|
||||
|
||||
private final DomainResultAssembler<T> assembler;
|
||||
|
||||
public ScalarDomainResultImpl(
|
||||
String resultVariable,
|
||||
SqmExpressable<T> expressableType) {
|
||||
this.resultVariable = resultVariable;
|
||||
this.expressableType = expressableType;
|
||||
|
||||
this.assembler = new BasicResultAssembler<>( expressableType );
|
||||
}
|
||||
|
||||
public ScalarDomainResultImpl(
|
||||
String resultVariable,
|
||||
SqmExpressable<T> expressableType,
|
||||
BasicValueConverter<T,?> valueConverter) {
|
||||
this.resultVariable = resultVariable;
|
||||
this.expressableType = expressableType;
|
||||
|
||||
this.assembler = new BasicResultAssembler<>( expressableType, valueConverter );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResultVariable() {
|
||||
return resultVariable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getResultJavaTypeDescriptor() {
|
||||
return expressableType.getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResultAssembler<T> createResultAssembler(
|
||||
Consumer<Initializer> initializerCollector,
|
||||
AssemblerCreationState creationState) {
|
||||
return assembler;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ package org.hibernate.sql.results.spi;
|
|||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Represents a result value in the domain query results. Acts as the
|
||||
|
@ -31,18 +31,16 @@ import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptor;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DomainResult extends ResultSetMappingNode {
|
||||
public interface DomainResult<J> extends ResultSetMappingNode {
|
||||
/**
|
||||
* The result-variable (alias) associated with this result.
|
||||
*/
|
||||
String getResultVariable();
|
||||
|
||||
JavaTypeDescriptor getJavaTypeDescriptor();
|
||||
|
||||
/**
|
||||
* Create an assembler (and any initializers) for this result.
|
||||
*/
|
||||
DomainResultAssembler createResultAssembler(
|
||||
DomainResultAssembler<J> createResultAssembler(
|
||||
Consumer<Initializer> initializerCollector,
|
||||
AssemblerCreationState creationState);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.spi;
|
||||
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Responsible for "assembling" a result for inclusion in the domain query
|
||||
* result. "Assembling" the result basically means building the result object
|
||||
|
@ -14,5 +16,22 @@ package org.hibernate.sql.results.spi;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DomainResultAssembler {
|
||||
public interface DomainResultAssembler<J> {
|
||||
/**
|
||||
* The main "assembly" contract. Assemble the result and return it.
|
||||
*/
|
||||
Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options);
|
||||
|
||||
/**
|
||||
* Convenience form of {@link #assemble(RowProcessingState, JdbcValuesSourceProcessingOptions)}
|
||||
*/
|
||||
default Object assemble(RowProcessingState rowProcessingState) {
|
||||
return assemble( rowProcessingState, rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions() );
|
||||
}
|
||||
|
||||
/**
|
||||
* The JavaTypeDescriptor describing the Java type that this assembler
|
||||
* assembles.
|
||||
*/
|
||||
JavaTypeDescriptor<J> getJavaTypeDescriptor();
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@ package org.hibernate.sql.results.spi;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DomainResultProducer {
|
||||
public interface DomainResultProducer<T> {
|
||||
/**
|
||||
* Produce the domain query
|
||||
*/
|
||||
DomainResult createDomainResult(
|
||||
DomainResult<T> createDomainResult(
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ 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
|
||||
|
@ -26,9 +27,13 @@ public interface JdbcValuesMapping {
|
|||
*/
|
||||
Set<SqlSelection> getSqlSelections();
|
||||
|
||||
List<DomainResult> getDomainResults();
|
||||
List<DomainResult<?>> getDomainResults();
|
||||
|
||||
List<DomainResultAssembler> resolveAssemblers(
|
||||
default List<DomainResultAssembler<?>> resolveAssemblers(
|
||||
Consumer<Initializer> initializerConsumer,
|
||||
AssemblerCreationState creationState);
|
||||
AssemblerCreationState creationState) {
|
||||
return getDomainResults().stream()
|
||||
.map( domainResult -> domainResult.createResultAssembler( initializerConsumer, creationState ) )
|
||||
.collect( Collectors.toList() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.io.Serializable;
|
||||
|
||||
/**
|
||||
* Essentially processing options only for entity loading
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcValuesSourceProcessingOptions {
|
||||
Object getEffectiveOptionalObject();
|
||||
String getEffectiveOptionalEntityName();
|
||||
Serializable getEffectiveOptionalId();
|
||||
|
||||
boolean shouldReturnProxies();
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.loading.internal.LoadingCollectionEntry;
|
||||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.spi.PostLoadEvent;
|
||||
import org.hibernate.event.spi.PreLoadEvent;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
||||
/**
|
||||
* Provides a context for processing the processing of the complete
|
||||
* set of rows from a JdbcValuesSource. Holds in-flight state
|
||||
* and provides access to environmental information needed to perform the
|
||||
* processing.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcValuesSourceProcessingState {
|
||||
ExecutionContext getExecutionContext();
|
||||
|
||||
default SharedSessionContractImplementor getSession() {
|
||||
return getExecutionContext().getSession();
|
||||
}
|
||||
|
||||
default QueryOptions getQueryOptions() {
|
||||
return getExecutionContext().getQueryOptions();
|
||||
}
|
||||
|
||||
JdbcValuesSourceProcessingOptions getProcessingOptions();
|
||||
|
||||
PreLoadEvent getPreLoadEvent();
|
||||
PostLoadEvent getPostLoadEvent();
|
||||
|
||||
/**
|
||||
* Find a LoadingEntityEntry locally to this context.
|
||||
*
|
||||
* @see LoadContexts#findLoadingEntityEntry(EntityKey)
|
||||
*/
|
||||
LoadingEntityEntry findLoadingEntityLocally(EntityKey entityKey);
|
||||
|
||||
/**
|
||||
* Registers a LoadingEntityEntry locally to this context
|
||||
*/
|
||||
void registerLoadingEntity(
|
||||
EntityKey entityKey,
|
||||
LoadingEntityEntry loadingEntry);
|
||||
|
||||
/**
|
||||
* Find a LoadingCollectionEntry locally to this context.
|
||||
*
|
||||
* @see LoadContexts#findLoadingCollectionEntry(CollectionKey)
|
||||
*/
|
||||
LoadingCollectionEntry findLoadingCollectionLocally(CollectionKey key);
|
||||
|
||||
/**
|
||||
* Registers a LoadingCollectionEntry locally to this context
|
||||
*/
|
||||
void registerLoadingCollection(
|
||||
CollectionKey collectionKey,
|
||||
LoadingCollectionEntry loadingCollectionEntry);
|
||||
|
||||
void finishUp();
|
||||
}
|
|
@ -19,7 +19,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
public interface ResultSetMappingNode {
|
||||
// todo (6.0) : result variable (selection alias)? - even fetches can have alias
|
||||
|
||||
JavaTypeDescriptor getJavaTypeDescriptor();
|
||||
JavaTypeDescriptor getResultJavaTypeDescriptor();
|
||||
|
||||
/**
|
||||
* The NavigablePath for this node (if one!). Certain nodes will not
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.query.NavigablePath;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
JdbcValuesSourceProcessingState getJdbcValuesSourceProcessingState();
|
||||
|
||||
void finishRowProcessing();
|
||||
|
||||
Initializer resolveInitializer(NavigablePath path);
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* Represent a simple scalar return within a query result. Generally this would be values of basic (String, Integer,
|
||||
* etc) or composite types.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface ScalarDomainResult<J> extends DomainResult<J> {
|
||||
}
|
|
@ -6,10 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.type;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.model.domain.AllowableOutputParameterType;
|
||||
|
||||
/**
|
||||
* Optional {@link Type} contract for implementations that are aware of how to extract values from
|
||||
|
@ -17,39 +14,5 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ProcedureParameterExtractionAware<T> {
|
||||
/**
|
||||
* Can the given instance of this type actually perform the parameter value extractions?
|
||||
*
|
||||
* @return {@code true} indicates that @{link #extract} calls will not fail due to {@link IllegalStateException}.
|
||||
*/
|
||||
boolean canDoExtraction();
|
||||
|
||||
/**
|
||||
* Perform the extraction
|
||||
*
|
||||
* @param statement The CallableStatement from which to extract the parameter value(s).
|
||||
* @param startIndex The parameter index from which to start extracting; assumes the values (if multiple) are contiguous
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return The extracted value.
|
||||
*
|
||||
* @throws SQLException Indicates an issue calling into the CallableStatement
|
||||
* @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction}
|
||||
*/
|
||||
T extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session) throws SQLException;
|
||||
|
||||
/**
|
||||
* Perform the extraction
|
||||
*
|
||||
* @param statement The CallableStatement from which to extract the parameter value(s).
|
||||
* @param paramNames The parameter names.
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return The extracted value.
|
||||
*
|
||||
* @throws SQLException Indicates an issue calling into the CallableStatement
|
||||
* @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction}
|
||||
*/
|
||||
T extract(CallableStatement statement, String[] paramNames, SharedSessionContractImplementor session) throws SQLException;
|
||||
public interface ProcedureParameterExtractionAware<T> extends AllowableOutputParameterType<T> {
|
||||
}
|
||||
|
|
|
@ -512,6 +512,21 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
|
|||
|
||||
private final ConcurrentHashMap<Class,BasicType> basicTypeByJavaType = new ConcurrentHashMap<>();
|
||||
|
||||
public BasicType getBasicTypeForJavaType(Class<?> javaType) {
|
||||
final BasicType existing = basicTypeByJavaType.get( javaType );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final BasicType registeredType = getBasicTypeRegistry().getRegisteredType( javaType );
|
||||
if ( registeredType != null ) {
|
||||
basicTypeByJavaType.put( javaType, registeredType );
|
||||
return registeredType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public BasicType standardBasicTypeForJavaType(Class<?> javaType) {
|
||||
if ( javaType == null ) {
|
||||
return null;
|
||||
|
|
Loading…
Reference in New Issue