6 - SQM based on JPA type system
- further work on `org.hibernate.query` (especially `NamedQueryRepository` and friends) - initial work on `org.hibernate.sql.exec` - initial work on `org.hibernate.sql.results` - SemanticPathPart handling - NamedQueryMemento - work on ProcedureCall - continued work on `org.hibernate.sql.exec` - continued work on `org.hibernate.sql.results`
This commit is contained in:
parent
638c217e8a
commit
d6428c5b43
|
@ -17,10 +17,10 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.loading.internal.LoadContexts;
|
||||
import org.hibernate.internal.util.MarkerObject;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.sql.results.spi.LoadContexts;
|
||||
|
||||
/**
|
||||
* Represents the state of "stuff" Hibernate is tracking, including (not exhaustive):
|
||||
|
|
|
@ -10,13 +10,14 @@ import java.sql.CallableStatement;
|
|||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Specialization of DomainType for types that can be used as a
|
||||
* parameter output for a {@link org.hibernate.procedure.ProcedureCall}
|
||||
*
|
||||
* @apiNote Generally speaking, an allowable output parameter type
|
||||
* can only effectively be a basic type.
|
||||
* @apiNote We assume a type that maps to exactly one SQL value, hence
|
||||
* {@link #getSqlTypeDescriptor()}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -28,6 +29,11 @@ public interface AllowableOutputParameterType<J> extends AllowableParameterType<
|
|||
*/
|
||||
boolean canDoExtraction();
|
||||
|
||||
/**
|
||||
* Descriptor for the SQL type mapped by this type.
|
||||
*/
|
||||
SqlTypeDescriptor getSqlTypeDescriptor();
|
||||
|
||||
/**
|
||||
* Perform the extraction
|
||||
*
|
||||
|
@ -46,7 +52,7 @@ public interface AllowableOutputParameterType<J> extends AllowableParameterType<
|
|||
* Perform the extraction
|
||||
*
|
||||
* @param statement The CallableStatement from which to extract the parameter value(s).
|
||||
* @param paramNames The parameter names.
|
||||
* @param paramName The parameter names.
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return The extracted value.
|
||||
|
@ -54,5 +60,5 @@ public interface AllowableOutputParameterType<J> extends AllowableParameterType<
|
|||
* @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;
|
||||
J extract(CallableStatement statement, String paramName, SharedSessionContractImplementor session) throws SQLException;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ 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.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -34,7 +36,7 @@ public class FunctionReturnImpl implements FunctionReturnImplementor {
|
|||
|
||||
public FunctionReturnImpl(ProcedureCallImplementor procedureCall, AllowableOutputParameterType ormType) {
|
||||
this.procedureCall = procedureCall;
|
||||
this.jdbcTypeCode = ormType.getSqlTypeDescriptor().getJdbcTypeCode();
|
||||
this.jdbcTypeCode = ormType.getSqlTypeDescriptor().getSqlType();
|
||||
|
||||
this.ormType = ormType;
|
||||
}
|
||||
|
@ -57,7 +59,7 @@ public class FunctionReturnImpl implements FunctionReturnImplementor {
|
|||
.getDescriptor( getJdbcTypeCode() );
|
||||
final JavaTypeDescriptor javaTypeMapping = sqlTypeDescriptor
|
||||
.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
ormType = typeConfiguration.getBasicTypeRegistry().getBasicType( javaTypeMapping.getJavaType() );
|
||||
ormType = typeConfiguration.standardBasicTypeForJavaType( javaTypeMapping.getJavaType() );
|
||||
parameterExtractor = new JdbcCallParameterExtractorImpl( procedureCall.getProcedureName(), null, 0, ormType );
|
||||
refCursorExtractor = null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.sql.exec.spi;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Unifying contract for any SQL statement we want to execute via JDBC.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcOperation {
|
||||
/**
|
||||
* Get the SQL command we will be executing through JDBC PreparedStatement
|
||||
* or CallableStatement
|
||||
*/
|
||||
String getSql();
|
||||
|
||||
/**
|
||||
* Get the list of parameter binders for the generated PreparedStatement
|
||||
*/
|
||||
List<JdbcParameterBinder> getParameterBinders();
|
||||
|
||||
Set<String> getAffectedTableNames();
|
||||
}
|
|
@ -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.sql.exec.spi;
|
||||
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcParameter extends Expression {
|
||||
JdbcParameterBinder getParameterBinder();
|
||||
}
|
|
@ -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.exec.spi;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Performs parameter value binding to a JDBC PreparedStatement.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author John O'Hara
|
||||
*/
|
||||
public interface JdbcParameterBinder {
|
||||
/**
|
||||
* Bind the appropriate value in the JDBC statement
|
||||
*/
|
||||
void bindParameterValue(
|
||||
PreparedStatement statement,
|
||||
int startPosition,
|
||||
JdbcParameterBindings jdbcParameterBindings,
|
||||
ExecutionContext executionContext) throws SQLException;
|
||||
}
|
|
@ -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.exec.spi;
|
||||
|
||||
import org.hibernate.sql.SqlExpressableType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcParameterBinding {
|
||||
SqlExpressableType getBindType();
|
||||
Object getBindValue();
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.sql.exec.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* Access to all of the externalized JDBC parameter bindings
|
||||
*
|
||||
* @apiNote "Externalized" because some JDBC parameter values are
|
||||
* intrinsically part of the parameter itself and we do not need to
|
||||
* locate a JdbcParameterBinding. E.g., consider a
|
||||
* {@link org.hibernate.sql.ast.tree.expression.LiteralParameter}
|
||||
* which actually encapsulates the actually literal value inside
|
||||
* itself - to create the binder and actually perform the binding
|
||||
* is only dependent on the LiteralParameter
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcParameterBindings {
|
||||
void addBinding(JdbcParameter parameter, JdbcParameterBinding binding);
|
||||
|
||||
Collection<JdbcParameterBinding> getBindings();
|
||||
|
||||
JdbcParameterBinding getBinding(JdbcParameter parameter);
|
||||
|
||||
void visitBindings(BiConsumer<JdbcParameter, JdbcParameterBinding> action);
|
||||
|
||||
JdbcParameterBindings NO_BINDINGS = new JdbcParameterBindings() {
|
||||
@Override
|
||||
public void addBinding(JdbcParameter parameter, JdbcParameterBinding binding) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<JdbcParameterBinding> getBindings() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcParameterBinding getBinding(JdbcParameter parameter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBindings(BiConsumer<JdbcParameter, JdbcParameterBinding> action) {
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.sql.exec.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* The collection
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcParameters {
|
||||
void addParameter(JdbcParameter parameter);
|
||||
void addParameters(Collection<JdbcParameter> parameters);
|
||||
|
||||
Set<JdbcParameter> getJdbcParameters();
|
||||
|
||||
default void visitJdbcParameters(Consumer<JdbcParameter> jdbcParameterAction) {
|
||||
for ( JdbcParameter jdbcParameter : getJdbcParameters() ) {
|
||||
jdbcParameterAction.accept( jdbcParameter );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
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;
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.sql.ResultSet;
|
||||
|
||||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.StandardStack;
|
||||
|
||||
/**
|
||||
* Maps {@link ResultSet result-sets} to specific contextual data related to processing that result set
|
||||
* <p/>
|
||||
* Considering the JDBC-redesign work, would further like this contextual info not mapped separately, but available
|
||||
* based on the result set being processed. This would also allow maintaining a single mapping as we could reliably
|
||||
* get notification of the result-set closing...
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LoadContexts {
|
||||
private static final CoreMessageLogger log = CoreLogging.messageLogger( LoadContexts.class );
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final StandardStack<JdbcValuesSourceProcessingState> jdbcValuesSourceProcessingStateStack = new StandardStack<>();
|
||||
|
||||
public LoadContexts(PersistenceContext persistenceContext) {
|
||||
this.persistenceContext = persistenceContext;
|
||||
}
|
||||
|
||||
public void register(JdbcValuesSourceProcessingState state) {
|
||||
jdbcValuesSourceProcessingStateStack.push( state );
|
||||
}
|
||||
|
||||
public void deregister(JdbcValuesSourceProcessingState state) {
|
||||
final JdbcValuesSourceProcessingState previous = jdbcValuesSourceProcessingStateStack.pop();
|
||||
if ( previous != state ) {
|
||||
throw new IllegalStateException( "Illegal pop() with non-matching JdbcValuesSourceProcessingState" );
|
||||
}
|
||||
}
|
||||
|
||||
public LoadingEntityEntry findLoadingEntityEntry(EntityKey entityKey) {
|
||||
return jdbcValuesSourceProcessingStateStack.findCurrentFirst(
|
||||
state -> state.findLoadingEntityLocally( entityKey )
|
||||
);
|
||||
}
|
||||
|
||||
public LoadingCollectionEntry findLoadingCollectionEntry(CollectionKey collectionKey) {
|
||||
return jdbcValuesSourceProcessingStateStack.findCurrentFirst(
|
||||
state -> state.findLoadingCollectionLocally( collectionKey )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the persistence context to which this is bound.
|
||||
*
|
||||
* @return The persistence context to which this is bound.
|
||||
*/
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
private SharedSessionContractImplementor getSession() {
|
||||
return getPersistenceContext().getSession();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release internal state associated with *all* result sets.
|
||||
* <p/>
|
||||
* This is intended as a "failsafe" process to make sure we get everything
|
||||
* cleaned up and released.
|
||||
*/
|
||||
public void cleanup() {
|
||||
if ( ! jdbcValuesSourceProcessingStateStack.isEmpty() ) {
|
||||
log.debugf( "LoadContexts still contained JdbcValuesSourceProcessingState registrations on cleanup" );
|
||||
}
|
||||
jdbcValuesSourceProcessingStateStack.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.CollectionEntry;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.model.mapping.PersistentCollectionDescriptor;
|
||||
import org.hibernate.metamodel.model.mapping.internal.PersistentArrayDescriptorImpl;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
||||
/**
|
||||
* Represents a collection currently being loaded.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LoadingCollectionEntry {
|
||||
private final PersistentCollectionDescriptor collectionDescriptor;
|
||||
private final CollectionInitializer initializer;
|
||||
private final Object key;
|
||||
private final PersistentCollection collectionInstance;
|
||||
|
||||
public LoadingCollectionEntry(
|
||||
PersistentCollectionDescriptor collectionDescriptor,
|
||||
CollectionInitializer initializer,
|
||||
Object key,
|
||||
PersistentCollection collectionInstance) {
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.initializer = initializer;
|
||||
this.key = key;
|
||||
this.collectionInstance = collectionInstance;
|
||||
|
||||
collectionInstance.beforeInitialize( -1, getCollectionDescriptor() );
|
||||
collectionInstance.beginRead();
|
||||
}
|
||||
|
||||
public PersistentCollectionDescriptor getCollectionDescriptor() {
|
||||
return collectionDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the initializer that is responsible for initializing this collection
|
||||
*/
|
||||
public CollectionInitializer getInitializer() {
|
||||
return initializer;
|
||||
}
|
||||
|
||||
public Object getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public PersistentCollection getCollectionInstance() {
|
||||
return collectionInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "(" + getCollectionDescriptor().getNavigableRole().getFullPath() + "#" + getKey() + ")";
|
||||
}
|
||||
|
||||
public void finishLoading(ExecutionContext executionContext) {
|
||||
collectionInstance.endRead();
|
||||
|
||||
final SharedSessionContractImplementor session = executionContext.getSession();
|
||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||
|
||||
CollectionEntry collectionEntry = persistenceContext.getCollectionEntry( collectionInstance );
|
||||
|
||||
if ( collectionEntry == null ) {
|
||||
collectionEntry = persistenceContext.addInitializedCollection(
|
||||
getCollectionDescriptor(),
|
||||
getCollectionInstance(),
|
||||
getKey()
|
||||
);
|
||||
}
|
||||
else {
|
||||
collectionEntry.postInitialize( collectionInstance );
|
||||
}
|
||||
|
||||
if ( getCollectionDescriptor() instanceof PersistentArrayDescriptorImpl ) {
|
||||
persistenceContext.addCollectionHolder( collectionInstance );
|
||||
}
|
||||
|
||||
|
||||
// todo (6.0) : there is other logic still needing to be implemented here. caching, etc
|
||||
// see org.hibernate.engine.loading.internal.CollectionLoadContext#endLoadingCollection in 5.x
|
||||
}
|
||||
}
|
|
@ -386,10 +386,10 @@ public abstract class AbstractStandardBasicType<T>
|
|||
}
|
||||
|
||||
@Override
|
||||
public T extract(CallableStatement statement, String[] paramNames, final SharedSessionContractImplementor session) throws SQLException {
|
||||
public T extract(CallableStatement statement, String paramName, final SharedSessionContractImplementor session) throws SQLException {
|
||||
return remapSqlTypeDescriptor( session ).getExtractor( javaTypeDescriptor ).extract(
|
||||
statement,
|
||||
paramNames,
|
||||
paramName,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
|
|
@ -808,7 +808,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object extract(CallableStatement statement, String[] paramNames, SharedSessionContractImplementor session)
|
||||
public Object extract(CallableStatement statement, String paramName, SharedSessionContractImplementor session)
|
||||
throws SQLException {
|
||||
// for this form to work all sub-property spans must be one (1)...
|
||||
|
||||
|
@ -816,7 +816,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
|
||||
int indx = 0;
|
||||
boolean notNull = false;
|
||||
for ( String paramName : paramNames ) {
|
||||
for ( String paramName : paramName ) {
|
||||
// we know this cast is safe from canDoExtraction
|
||||
final ProcedureParameterExtractionAware propertyType = (ProcedureParameterExtractionAware) propertyTypes[indx];
|
||||
final Object value = propertyType.extract( statement, new String[] {paramName}, session );
|
||||
|
|
|
@ -326,10 +326,10 @@ public class CustomType
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object extract(CallableStatement statement, String[] paramNames, SharedSessionContractImplementor session)
|
||||
public Object extract(CallableStatement statement, String paramName, SharedSessionContractImplementor session)
|
||||
throws SQLException {
|
||||
if ( canDoExtraction() ) {
|
||||
return ((ProcedureParameterExtractionAware) getUserType() ).extract( statement, paramNames, session );
|
||||
return ((ProcedureParameterExtractionAware) getUserType() ).extract( statement, paramName, session );
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(
|
||||
|
|
Loading…
Reference in New Issue