Add the Object type to the basic type registry and resolve it by Java type instead of referring to JavaObjectType or StandardBasicTypes.OBJECT_TYPE
Also add special JdbcTypeDescriptor implementations that resolve the parameter type or use a VARBINARY on null values, as needed for some dialects, which register these descriptors
This commit is contained in:
parent
05f643f208
commit
10e508dfe7
|
@ -792,52 +792,57 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
protected <T> QueryImplementor<T> buildNamedQuery(String queryName, Class<T> resultType) {
|
||||
checkOpen();
|
||||
pulseTransactionCoordinator();
|
||||
delayedAfterCompletion();
|
||||
try {
|
||||
pulseTransactionCoordinator();
|
||||
delayedAfterCompletion();
|
||||
|
||||
// this method can be called for either a named HQL query or a named native query
|
||||
// this method can be called for either a named HQL query or a named native query
|
||||
|
||||
// first see if it is a named HQL query
|
||||
final NamedHqlQueryMemento namedHqlDescriptor = getFactory().getQueryEngine()
|
||||
.getNamedObjectRepository()
|
||||
.getHqlQueryMemento( queryName );
|
||||
// first see if it is a named HQL query
|
||||
final NamedHqlQueryMemento namedHqlDescriptor = getFactory().getQueryEngine()
|
||||
.getNamedObjectRepository()
|
||||
.getHqlQueryMemento( queryName );
|
||||
|
||||
if ( namedHqlDescriptor != null ) {
|
||||
HqlQueryImplementor<T> query = namedHqlDescriptor.toQuery( this, resultType );
|
||||
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||
query.setComment( "dynamic HQL query" );
|
||||
if ( namedHqlDescriptor != null ) {
|
||||
HqlQueryImplementor<T> query = namedHqlDescriptor.toQuery( this, resultType );
|
||||
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||
query.setComment( "dynamic HQL query" );
|
||||
}
|
||||
applyQuerySettingsAndHints( query );
|
||||
if ( namedHqlDescriptor.getLockOptions() != null ) {
|
||||
query.setLockOptions( namedHqlDescriptor.getLockOptions() );
|
||||
}
|
||||
return query;
|
||||
}
|
||||
applyQuerySettingsAndHints( query );
|
||||
if ( namedHqlDescriptor.getLockOptions() != null ) {
|
||||
query.setLockOptions( namedHqlDescriptor.getLockOptions() );
|
||||
|
||||
// otherwise, see if it is a named native query
|
||||
final NamedNativeQueryMemento namedNativeDescriptor = getFactory().getQueryEngine()
|
||||
.getNamedObjectRepository()
|
||||
.getNativeQueryMemento( queryName );
|
||||
|
||||
if ( namedNativeDescriptor != null ) {
|
||||
final NativeQueryImplementor<T> query;
|
||||
if ( resultType == null) {
|
||||
query = namedNativeDescriptor.toQuery( this );
|
||||
}
|
||||
else {
|
||||
query = namedNativeDescriptor.toQuery( this, resultType );
|
||||
}
|
||||
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||
query.setComment( "dynamic native SQL query" );
|
||||
}
|
||||
applyQuerySettingsAndHints( query );
|
||||
return query;
|
||||
}
|
||||
return query;
|
||||
|
||||
// todo (6.0) : allow this for named stored procedures as well?
|
||||
// ultimately they are treated as a Query
|
||||
|
||||
throw getExceptionConverter().convert( new IllegalArgumentException( "No query defined for that name [" + queryName + "]" ) );
|
||||
}
|
||||
|
||||
// otherwise, see if it is a named native query
|
||||
final NamedNativeQueryMemento namedNativeDescriptor = getFactory().getQueryEngine()
|
||||
.getNamedObjectRepository()
|
||||
.getNativeQueryMemento( queryName );
|
||||
|
||||
if ( namedNativeDescriptor != null ) {
|
||||
final NativeQueryImplementor<T> query;
|
||||
if ( resultType == null) {
|
||||
query = namedNativeDescriptor.toQuery( this );
|
||||
}
|
||||
else {
|
||||
query = namedNativeDescriptor.toQuery( this, resultType );
|
||||
}
|
||||
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||
query.setComment( "dynamic native SQL query" );
|
||||
}
|
||||
applyQuerySettingsAndHints( query );
|
||||
return query;
|
||||
catch (RuntimeException e) {
|
||||
throw !( e instanceof IllegalArgumentException ) ? new IllegalArgumentException( e ) : e;
|
||||
}
|
||||
|
||||
// todo (6.0) : allow this for named stored procedures as well?
|
||||
// ultimately they are treated as a Query
|
||||
|
||||
throw getExceptionConverter().convert( new IllegalArgumentException( "No query defined for that name [" + queryName + "]" ) );
|
||||
}
|
||||
|
||||
protected void applyQuerySettingsAndHints(Query query) {
|
||||
|
|
|
@ -26,8 +26,7 @@ import org.hibernate.sql.ast.tree.from.TableReference;
|
|||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -37,11 +36,14 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping, SelectableMap
|
|||
private final String rowIdName;
|
||||
private final EntityMappingType declaringType;
|
||||
private final String tableExpression;
|
||||
private final BasicType<Object> rowIdType;
|
||||
|
||||
public EntityRowIdMappingImpl(String rowIdName, String tableExpression, EntityMappingType declaringType) {
|
||||
this.rowIdName = rowIdName;
|
||||
this.tableExpression = tableExpression;
|
||||
this.declaringType = declaringType;
|
||||
this.rowIdType = declaringType.getEntityPersister().getFactory().getTypeConfiguration()
|
||||
.getBasicTypeForJavaType( Object.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,12 +53,12 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping, SelectableMap
|
|||
|
||||
@Override
|
||||
public MappingType getPartMappingType() {
|
||||
return this::getJavaTypeDescriptor;
|
||||
return rowIdType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<?> getJavaTypeDescriptor() {
|
||||
return JavaObjectType.INSTANCE.getJavaTypeDescriptor();
|
||||
return rowIdType.getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,18 +100,18 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping, SelectableMap
|
|||
// having to write a Dialect
|
||||
null,
|
||||
null,
|
||||
JavaObjectType.INSTANCE,
|
||||
rowIdType,
|
||||
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||
)
|
||||
),
|
||||
JavaObjectType.INSTANCE.getJdbcMapping().getJavaTypeDescriptor(),
|
||||
rowIdType.getJavaTypeDescriptor(),
|
||||
sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
|
||||
return new BasicResult(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
resultVariable,
|
||||
getJavaTypeDescriptor(),
|
||||
rowIdType.getJavaTypeDescriptor(),
|
||||
navigablePath
|
||||
);
|
||||
}
|
||||
|
@ -121,7 +123,7 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping, SelectableMap
|
|||
|
||||
@Override
|
||||
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
|
||||
action.accept( offset, JavaObjectType.INSTANCE );
|
||||
action.accept( offset, getJdbcMapping() );
|
||||
return getJdbcTypeCount();
|
||||
}
|
||||
|
||||
|
@ -170,6 +172,6 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping, SelectableMap
|
|||
|
||||
@Override
|
||||
public JdbcMapping getJdbcMapping() {
|
||||
return StandardBasicTypes.INTEGER;
|
||||
return rowIdType.getJdbcMapping();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,6 +180,7 @@ import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
|
|||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
|
@ -3037,7 +3038,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
}
|
||||
|
||||
private <J> BasicDomainType<J> resolveExpressableTypeBasic(Class<J> javaType) {
|
||||
private <J> BasicType<J> resolveExpressableTypeBasic(Class<J> javaType) {
|
||||
return creationContext.getJpaMetamodel().getTypeConfiguration().standardBasicTypeForJavaType( javaType );
|
||||
}
|
||||
|
||||
|
@ -3093,7 +3094,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
functionName,
|
||||
true,
|
||||
null,
|
||||
StandardFunctionReturnTypeResolvers.invariant( StandardBasicTypes.OBJECT_TYPE )
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
resolveExpressableTypeBasic( Object.class )
|
||||
)
|
||||
);
|
||||
}
|
||||
return functionTemplate.generateSqmExpression(
|
||||
|
@ -3137,7 +3140,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
functionName,
|
||||
true,
|
||||
null,
|
||||
StandardFunctionReturnTypeResolvers.invariant( StandardBasicTypes.OBJECT_TYPE ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
resolveExpressableTypeBasic( Object.class )
|
||||
),
|
||||
functionName,
|
||||
filterExpression != null ? FunctionKind.AGGREGATE : FunctionKind.NORMAL,
|
||||
null,
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
@ -19,7 +18,7 @@ import org.hibernate.query.QueryParameter;
|
|||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
import org.hibernate.query.spi.QueryParameterBindingTypeResolver;
|
||||
import org.hibernate.query.spi.QueryParameterBindingValidator;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.NullType;
|
||||
import org.hibernate.type.descriptor.java.CoercionException;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -101,7 +100,7 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setBindValue(T value) {
|
||||
public void setBindValue(T value, boolean resolveJdbcTypeIfNecessary) {
|
||||
if ( handleAsMultiValue( value ) ) {
|
||||
return;
|
||||
}
|
||||
|
@ -119,6 +118,10 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
|
|||
validate( value );
|
||||
}
|
||||
|
||||
if ( resolveJdbcTypeIfNecessary && bindType == null && value == null ) {
|
||||
//noinspection unchecked
|
||||
bindType = (AllowableParameterType<T>) NullType.INSTANCE;
|
||||
}
|
||||
bindValue( value );
|
||||
}
|
||||
|
||||
|
@ -148,9 +151,11 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
|
|||
this.isBound = true;
|
||||
this.bindValue = value;
|
||||
|
||||
if ( bindType == null && value != null ) {
|
||||
//noinspection unchecked
|
||||
this.bindType = (AllowableParameterType) typeResolver.resolveParameterBindType( value );
|
||||
if ( bindType == null ) {
|
||||
if ( value != null ) {
|
||||
//noinspection unchecked
|
||||
this.bindType = (AllowableParameterType<T>) typeResolver.resolveParameterBindType( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -752,6 +752,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// QueryParameter handling
|
||||
|
||||
protected boolean resolveJdbcParameterTypeIfNecessary() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( {"unchecked", "rawtypes"} )
|
||||
public Set<Parameter<?>> getParameters() {
|
||||
|
@ -943,7 +947,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
|
||||
@Override
|
||||
public <P> QueryImplementor<R> setParameter(QueryParameter<P> parameter, P value) {
|
||||
locateBinding( parameter ).setBindValue( value );
|
||||
locateBinding( parameter ).setBindValue( value, resolveJdbcParameterTypeIfNecessary() );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -953,7 +957,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
setParameter( parameter, ( (TypedParameterValue) value ).getValue(), ( (TypedParameterValue) value ).getType() );
|
||||
}
|
||||
else {
|
||||
locateBinding( parameter ).setBindValue( value );
|
||||
locateBinding( parameter ).setBindValue( value, resolveJdbcParameterTypeIfNecessary() );
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -986,7 +990,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
setParameterList( name, (Collection) value );
|
||||
}
|
||||
else {
|
||||
locateBinding( name ).setBindValue( value );
|
||||
locateBinding( name ).setBindValue( value, resolveJdbcParameterTypeIfNecessary() );
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -1003,7 +1007,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
setParameterList( position, (Collection<?>) value );
|
||||
}
|
||||
else {
|
||||
locateBinding( position ).setBindValue( value );
|
||||
locateBinding( position ).setBindValue( value, resolveJdbcParameterTypeIfNecessary() );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,15 @@ public interface QueryParameterBinding<T> {
|
|||
/**
|
||||
* Sets the parameter binding value. The inherent parameter type (if known) is assumed
|
||||
*/
|
||||
void setBindValue(T value);
|
||||
default void setBindValue(T value) {
|
||||
setBindValue( value, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameter binding value. The inherent parameter type (if known) is assumed.
|
||||
* The flag controls whether the parameter type should be resolved if necessary.
|
||||
*/
|
||||
void setBindValue(T value, boolean resolveJdbcTypeIfNecessary);
|
||||
|
||||
/**
|
||||
* Sets the parameter binding value using the explicit Type.
|
||||
|
|
|
@ -11,49 +11,25 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.action.internal.BulkOperationCleanupAction;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelHelper;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
import org.hibernate.query.spi.SqlOmittingQueryOptions;
|
||||
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
||||
import org.hibernate.query.sqm.internal.SqmUtil;
|
||||
import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.MutatingTableReferenceGroupWrapper;
|
||||
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
|
||||
import org.hibernate.sql.exec.internal.StandardJdbcMutationExecutor;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||
import org.hibernate.sql.exec.spi.JdbcMutation;
|
||||
import org.hibernate.sql.exec.spi.JdbcMutationExecutor;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||
import org.hibernate.sql.exec.spi.JdbcSelect;
|
||||
import org.hibernate.sql.exec.spi.JdbcSelectExecutor;
|
||||
import org.hibernate.sql.exec.spi.NativeJdbcMutation;
|
||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||
import org.hibernate.sql.results.spi.RowTransformer;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -96,7 +72,7 @@ public class NativeNonSelectQueryPlanImpl implements NonSelectQueryPlan {
|
|||
type = param.getHibernateType();
|
||||
}
|
||||
if ( type == null ) {
|
||||
type = StandardBasicTypes.OBJECT_TYPE;
|
||||
type = executionContext.getSession().getTypeConfiguration().getBasicTypeForJavaType( Object.class );
|
||||
}
|
||||
|
||||
final JdbcMapping jdbcMapping = ( (BasicValuedMapping) type ).getJdbcMapping();
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.hibernate.sql.exec.spi.JdbcSelect;
|
|||
import org.hibernate.sql.exec.spi.JdbcSelectExecutor;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -92,7 +91,7 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
|
|||
type = param.getHibernateType();
|
||||
}
|
||||
if ( type == null ) {
|
||||
type = StandardBasicTypes.OBJECT_TYPE;
|
||||
type = executionContext.getSession().getTypeConfiguration().getBasicTypeForJavaType( Object.class );
|
||||
}
|
||||
|
||||
final JdbcMapping jdbcMapping = ( (BasicValuedMapping) type ).getJdbcMapping();
|
||||
|
@ -157,7 +156,7 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
|
|||
type = param.getHibernateType();
|
||||
}
|
||||
if ( type == null ) {
|
||||
type = StandardBasicTypes.OBJECT_TYPE;
|
||||
type = executionContext.getSession().getTypeConfiguration().getBasicTypeForJavaType( Object.class );
|
||||
}
|
||||
|
||||
final JdbcMapping jdbcMapping = ( (BasicValuedMapping) type ).getJdbcMapping();
|
||||
|
|
|
@ -505,6 +505,12 @@ public class QuerySqmImpl<R>
|
|||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean resolveJdbcParameterTypeIfNecessary() {
|
||||
// No need to resolve JDBC parameter types as we know them from the SQM model
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockModeType getLockMode() {
|
||||
if ( ! isSelectQuery() ) {
|
||||
|
|
|
@ -258,7 +258,6 @@ import org.hibernate.sql.ast.tree.expression.ExtractUnit;
|
|||
import org.hibernate.sql.ast.tree.expression.Format;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.expression.NullnessLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
|
||||
|
@ -313,7 +312,6 @@ import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
|||
import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.VersionType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptorIndicators;
|
||||
|
@ -1732,7 +1730,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
selection.getValuesArrayPosition(),
|
||||
new QueryLiteral<>(
|
||||
selection.getValuesArrayPosition(),
|
||||
StandardBasicTypes.INTEGER
|
||||
basicType( Integer.class )
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -2657,8 +2655,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
|
||||
private Expression createCaseExpression(SqmPath<?> lhs, EntityDomainType<?> treatTarget, Expression expression) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
final MappingModelExpressable mappingModelExpressable = (MappingModelExpressable) expression.getExpressionType();
|
||||
final BasicValuedMapping mappingModelExpressable = (BasicValuedMapping) expression.getExpressionType();
|
||||
final List<CaseSearchedExpression.WhenFragment> whenFragments = new ArrayList<>( 1 );
|
||||
whenFragments.add(
|
||||
new CaseSearchedExpression.WhenFragment(
|
||||
|
@ -2669,7 +2666,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return new CaseSearchedExpression(
|
||||
mappingModelExpressable,
|
||||
whenFragments,
|
||||
new NullnessLiteral( mappingModelExpressable )
|
||||
new QueryLiteral<>( null, mappingModelExpressable )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2702,18 +2699,17 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final Supplier<MappingModelExpressable> inferableTypeAccess = inferrableTypeAccessStack.getCurrent();
|
||||
|
||||
if ( literal instanceof SqmLiteralNull ) {
|
||||
MappingModelExpressable mappingModelExpressable = inferableTypeAccess.get();
|
||||
MappingModelExpressable<?> mappingModelExpressable = inferableTypeAccess.get();
|
||||
if ( mappingModelExpressable == null ) {
|
||||
mappingModelExpressable = determineCurrentExpressable( literal );
|
||||
}
|
||||
if ( mappingModelExpressable instanceof BasicValuedMapping ) {
|
||||
return new NullnessLiteral( mappingModelExpressable );
|
||||
return new QueryLiteral<>( null, (BasicValuedMapping) mappingModelExpressable );
|
||||
}
|
||||
final MappingModelExpressable keyExpressable = getKeyExpressable( mappingModelExpressable );
|
||||
final MappingModelExpressable<?> keyExpressable = getKeyExpressable( mappingModelExpressable );
|
||||
if ( keyExpressable == null ) {
|
||||
// todo (6.0): this should be fine, right?
|
||||
return new NullnessLiteral( JavaObjectType.INSTANCE );
|
||||
// throw new IllegalArgumentException( "Could not determine type for null literal" );
|
||||
// Default to the Object type
|
||||
return new QueryLiteral<>( null, basicType( Object.class ) );
|
||||
}
|
||||
|
||||
final List<Expression> expressions = new ArrayList<>( keyExpressable.getJdbcTypeCount() );
|
||||
|
@ -2729,11 +2725,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return new SqlTuple( expressions, mappingModelExpressable );
|
||||
}
|
||||
|
||||
final MappingModelExpressable inferableExpressable = inferableTypeAccess.get();
|
||||
final MappingModelExpressable<?> inferableExpressable = inferableTypeAccess.get();
|
||||
|
||||
if ( inferableExpressable instanceof ConvertibleModelPart ) {
|
||||
final ConvertibleModelPart convertibleModelPart = (ConvertibleModelPart) inferableExpressable;
|
||||
final BasicValueConverter valueConverter = convertibleModelPart.getValueConverter();
|
||||
final BasicValueConverter<Object, Object> valueConverter = convertibleModelPart.getValueConverter();
|
||||
|
||||
if ( valueConverter != null ) {
|
||||
final Object literalValue = literal.getLiteralValue();
|
||||
|
@ -2770,7 +2766,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
.getEntityDescriptor( (Class<?>) literalValue );
|
||||
}
|
||||
else {
|
||||
final JavaTypeDescriptor javaTypeDescriptor = discriminatorMapping.getJdbcMapping().getJavaTypeDescriptor();
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor = discriminatorMapping.getJdbcMapping().getJavaTypeDescriptor();
|
||||
final Object discriminatorValue;
|
||||
if ( javaTypeDescriptor.getJavaTypeClass().isInstance( literalValue ) ) {
|
||||
discriminatorValue = literalValue;
|
||||
|
@ -2793,8 +2789,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return new EntityTypeLiteral( mappingDescriptor );
|
||||
}
|
||||
|
||||
final MappingModelExpressable expressable;
|
||||
final MappingModelExpressable localExpressable = SqmMappingModelHelper.resolveMappingModelExpressable(
|
||||
final MappingModelExpressable<?> expressable;
|
||||
final MappingModelExpressable<?> localExpressable = SqmMappingModelHelper.resolveMappingModelExpressable(
|
||||
literal,
|
||||
getCreationContext().getDomainModel(),
|
||||
getFromClauseAccess()::findTableGroup
|
||||
|
@ -2803,7 +2799,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
expressable = getElementExpressable( inferableExpressable );
|
||||
}
|
||||
else {
|
||||
final MappingModelExpressable elementExpressable = getElementExpressable( localExpressable );
|
||||
final MappingModelExpressable<?> elementExpressable = getElementExpressable( localExpressable );
|
||||
if ( elementExpressable instanceof BasicType<?> ) {
|
||||
expressable = InferredBasicValueResolver.resolveSqlTypeIndicators(
|
||||
this,
|
||||
|
@ -3177,10 +3173,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
}
|
||||
|
||||
if ( parameterSqmType == null || parameterSqmType == StandardBasicTypes.OBJECT_TYPE ) {
|
||||
assert binding.getBindValue() == null;
|
||||
// todo (6.0): this should be fine, right?
|
||||
return StandardBasicTypes.OBJECT_TYPE;
|
||||
if ( parameterSqmType == null ) {
|
||||
// Default to the Object type
|
||||
return basicType( Object.class );
|
||||
}
|
||||
else if ( parameterSqmType instanceof MappingModelExpressable<?> && parameterSqmType.getJavaType() == Object.class ) {
|
||||
return (MappingModelExpressable<?>) parameterSqmType;
|
||||
}
|
||||
|
||||
if ( parameterSqmType instanceof SqmPath ) {
|
||||
|
@ -4086,7 +4084,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
}
|
||||
|
||||
private <J> BasicValuedMapping basicType(Class<J> javaType) {
|
||||
private <J> BasicType<J> basicType(Class<J> javaType) {
|
||||
return creationContext.getDomainModel().getTypeConfiguration().getBasicTypeForJavaType( javaType );
|
||||
}
|
||||
|
||||
|
@ -4928,7 +4926,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final int jdbcTypeCount = collectionKeyDescriptor.getJdbcTypeCount();
|
||||
assert jdbcTypeCount > 0;
|
||||
|
||||
final JdbcLiteral<Integer> jdbcLiteral = new JdbcLiteral<>( 1, StandardBasicTypes.INTEGER );
|
||||
final JdbcLiteral<Integer> jdbcLiteral = new JdbcLiteral<>( 1, basicType( Integer.class ) );
|
||||
subQuerySpec.getSelectClause().addSqlSelection(
|
||||
new SqlSelectionImpl( 1, 0, jdbcLiteral )
|
||||
);
|
||||
|
|
|
@ -45,8 +45,7 @@ public class LiteralHelper {
|
|||
}
|
||||
|
||||
public static SqmLiteral<Integer> integerLiteral(int value, QueryEngine queryEngine) {
|
||||
//noinspection unchecked
|
||||
return new SqmLiteral(
|
||||
return new SqmLiteral<>(
|
||||
value,
|
||||
StandardBasicTypes.INTEGER,
|
||||
queryEngine.getCriteriaBuilder()
|
||||
|
|
|
@ -30,9 +30,15 @@ public class SqmLiteral<T>
|
|||
|
||||
public SqmLiteral(T value, SqmExpressable<T> inherentType, NodeBuilder nodeBuilder) {
|
||||
super( inherentType, nodeBuilder );
|
||||
assert value != null;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
protected SqmLiteral(SqmExpressable<T> inherentType, NodeBuilder nodeBuilder) {
|
||||
super( inherentType, nodeBuilder );
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
public T getLiteralValue() {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -14,15 +14,16 @@ import org.hibernate.query.sqm.SemanticQueryWalker;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmLiteralNull<T> extends SqmLiteral<T> {
|
||||
|
||||
private static final SqmExpressable<Object> NULL_TYPE = () -> null;
|
||||
|
||||
public SqmLiteralNull(NodeBuilder nodeBuilder) {
|
||||
//noinspection unchecked
|
||||
this( NULL_TYPE, nodeBuilder );
|
||||
this( (SqmExpressable<T>) NULL_TYPE, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmLiteralNull(
|
||||
SqmExpressable<T> expressableType,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( null, expressableType, nodeBuilder );
|
||||
public SqmLiteralNull(SqmExpressable<T> expressableType, NodeBuilder nodeBuilder) {
|
||||
super( expressableType, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,8 +36,6 @@ public class SqmLiteralNull<T> extends SqmLiteral<T> {
|
|||
return "<literal-null>";
|
||||
}
|
||||
|
||||
private static SqmExpressable NULL_TYPE = () -> null;
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
sb.append( "null" );
|
||||
|
|
|
@ -11,7 +11,6 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
* Base support for {@link JpaTupleElement} impls
|
||||
|
@ -32,18 +31,6 @@ public abstract class AbstractJpaTupleElement<T>
|
|||
setExpressableType( expressableType );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected AbstractJpaTupleElement(Class<T> javaType, NodeBuilder criteriaBuilder) {
|
||||
super( criteriaBuilder );
|
||||
|
||||
if ( javaType != null ) {
|
||||
setJavaType( javaType );
|
||||
}
|
||||
else {
|
||||
setExpressableType( StandardBasicTypes.OBJECT_TYPE );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlias() {
|
||||
return alias;
|
||||
|
@ -65,20 +52,4 @@ public abstract class AbstractJpaTupleElement<T>
|
|||
this.expressableType = (SqmExpressable<T>) expressableType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected access to set the JavaTypeDescriptor via Java Class
|
||||
*/
|
||||
protected void setJavaType(Class<T> targetType) {
|
||||
if ( targetType != null ) {
|
||||
setExpressableType(
|
||||
nodeBuilder().getDomainModel()
|
||||
.getTypeConfiguration()
|
||||
.standardBasicTypeForJavaType( targetType )
|
||||
);
|
||||
}
|
||||
else {
|
||||
setExpressableType( StandardBasicTypes.OBJECT_TYPE );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -83,8 +83,9 @@ public abstract class AbstractJdbcParameter
|
|||
jdbcMapping = this.jdbcMapping;
|
||||
}
|
||||
|
||||
if ( jdbcMapping == null ) {
|
||||
jdbcMapping = guessBindType( executionContext, binding );
|
||||
// If the parameter type is not known from the context i.e. null or Object, infer it from the bind value
|
||||
if ( jdbcMapping == null || jdbcMapping.getMappedJavaTypeDescriptor().getJavaTypeClass() == Object.class ) {
|
||||
jdbcMapping = guessBindType( executionContext, binding, jdbcMapping );
|
||||
}
|
||||
|
||||
final Object bindValue = binding.getBindValue();
|
||||
|
@ -98,12 +99,22 @@ public abstract class AbstractJdbcParameter
|
|||
);
|
||||
}
|
||||
|
||||
private JdbcMapping guessBindType(ExecutionContext executionContext, JdbcParameterBinding binding) {
|
||||
private JdbcMapping guessBindType(ExecutionContext executionContext, JdbcParameterBinding binding, JdbcMapping jdbcMapping) {
|
||||
final Class<?> valueClass;
|
||||
if ( binding.getBindValue() == null ) {
|
||||
if ( jdbcMapping != null ) {
|
||||
return jdbcMapping;
|
||||
}
|
||||
valueClass = Object.class;
|
||||
}
|
||||
else {
|
||||
valueClass = binding.getBindValue().getClass();
|
||||
}
|
||||
final BasicType<?> basicType = executionContext.getSession()
|
||||
.getFactory()
|
||||
.getTypeConfiguration()
|
||||
.getBasicTypeRegistry()
|
||||
.getRegisteredType( binding.getBindValue().getClass() );
|
||||
.getRegisteredType( valueClass );
|
||||
|
||||
return basicType.getJdbcMapping();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.type;
|
||||
|
||||
import org.hibernate.type.descriptor.java.JavaObjectTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectJdbcTypeDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -22,8 +24,17 @@ public class JavaObjectType extends AbstractSingleColumnStandardBasicType<Object
|
|||
super( ObjectJdbcTypeDescriptor.INSTANCE, JavaObjectTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
public JavaObjectType(JdbcTypeDescriptor jdbcTypeDescriptor, JavaTypeDescriptor<Object> javaTypeDescriptor) {
|
||||
super( jdbcTypeDescriptor, javaTypeDescriptor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "JAVA_OBJECT";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean registerUnderJavaType() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.type;
|
||||
|
||||
import org.hibernate.type.descriptor.java.JavaObjectTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectJdbcTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectNullResolvingJdbcTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class NullType extends JavaObjectType {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final NullType INSTANCE = new NullType();
|
||||
|
||||
public NullType() {
|
||||
super( ObjectNullResolvingJdbcTypeDescriptor.INSTANCE, JavaObjectTypeDescriptor.INSTANCE );
|
||||
}
|
||||
}
|
|
@ -942,6 +942,13 @@ public final class StandardBasicTypes {
|
|||
DbTimestampType.INSTANCE.getName()
|
||||
);
|
||||
|
||||
handle(
|
||||
OBJECT_TYPE,
|
||||
null,
|
||||
basicTypeRegistry,
|
||||
"object", Object.class.getName()
|
||||
);
|
||||
|
||||
// todo (6.0) - ? how to handle DbTimestampType?
|
||||
// DbTimestampType was really just a variant of TimestampType with overridden
|
||||
// version (opt lock) support
|
||||
|
|
|
@ -19,7 +19,8 @@ import org.hibernate.type.descriptor.WrapperOptions;
|
|||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Descriptor for
|
||||
* Descriptor for binding objects
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ObjectJdbcTypeDescriptor implements JdbcTypeDescriptor {
|
||||
|
@ -72,25 +73,25 @@ public class ObjectJdbcTypeDescriptor implements JdbcTypeDescriptor {
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ValueExtractor getExtractor(JavaTypeDescriptor javaTypeDescriptor) {
|
||||
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
|
||||
return VarbinaryTypeDescriptor.INSTANCE.getExtractor( javaTypeDescriptor );
|
||||
}
|
||||
|
||||
return new BasicExtractor( javaTypeDescriptor, this ) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected Object doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return rs.getObject( paramIndex );
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return (X) rs.getObject( paramIndex );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return statement.getObject( index );
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return (X) statement.getObject( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return statement.getObject( name );
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return (X) statement.getObject( name );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.type.descriptor.jdbc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Descriptor for binding objects, but binding nulls with Types.VARBINARY
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class ObjectNullAsBinaryTypeJdbcTypeDescriptor extends ObjectJdbcTypeDescriptor {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final ObjectNullAsBinaryTypeJdbcTypeDescriptor INSTANCE = new ObjectNullAsBinaryTypeJdbcTypeDescriptor( Types.JAVA_OBJECT );
|
||||
|
||||
public ObjectNullAsBinaryTypeJdbcTypeDescriptor(int jdbcTypeCode) {
|
||||
super( jdbcTypeCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
|
||||
return VarbinaryTypeDescriptor.INSTANCE.getBinder( javaTypeDescriptor );
|
||||
}
|
||||
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
|
||||
@Override
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setNull( index, Types.VARBINARY );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setNull( name, Types.VARBINARY );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( index, value, getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( name, value, getJdbcTypeCode() );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.type.descriptor.jdbc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Descriptor for binding objects, but binding nulls with Types.NULL
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class ObjectNullAsNullTypeJdbcTypeDescriptor extends ObjectJdbcTypeDescriptor {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final ObjectNullAsNullTypeJdbcTypeDescriptor INSTANCE = new ObjectNullAsNullTypeJdbcTypeDescriptor( Types.JAVA_OBJECT );
|
||||
|
||||
public ObjectNullAsNullTypeJdbcTypeDescriptor(int jdbcTypeCode) {
|
||||
super( jdbcTypeCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
|
||||
return VarbinaryTypeDescriptor.INSTANCE.getBinder( javaTypeDescriptor );
|
||||
}
|
||||
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
|
||||
@Override
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setNull( index, Types.NULL );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setNull( name, Types.NULL );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( index, value, getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( name, value, getJdbcTypeCode() );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.type.descriptor.jdbc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Descriptor for binding objects, but binding nulls with the resolved parameter type
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class ObjectNullResolvingJdbcTypeDescriptor extends ObjectJdbcTypeDescriptor {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final ObjectNullResolvingJdbcTypeDescriptor INSTANCE = new ObjectNullResolvingJdbcTypeDescriptor( Types.JAVA_OBJECT );
|
||||
|
||||
public ObjectNullResolvingJdbcTypeDescriptor(int jdbcTypeCode) {
|
||||
super( jdbcTypeCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
|
||||
return VarbinaryTypeDescriptor.INSTANCE.getBinder( javaTypeDescriptor );
|
||||
}
|
||||
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
|
||||
@Override
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setNull( index, st.getParameterMetaData().getParameterType( index ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setNull( name, Types.JAVA_OBJECT );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( index, value, getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( name, value, getJdbcTypeCode() );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -53,7 +53,6 @@ import org.hibernate.query.sqm.tree.SqmTypedNode;
|
|||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.BasicTypeRegistry;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.SingleColumnType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
@ -477,7 +476,9 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
|
|||
final SqmExpressable<?>[] components = new SqmExpressable<?>[typedNodes.size()];
|
||||
for ( int i = 0; i < typedNodes.size(); i++ ) {
|
||||
final SqmExpressable<?> sqmExpressable = typedNodes.get( i ).getNodeType();
|
||||
components[i] = sqmExpressable == null ? JavaObjectType.INSTANCE : sqmExpressable;
|
||||
components[i] = sqmExpressable != null
|
||||
? sqmExpressable
|
||||
: getBasicTypeForJavaType( Object.class );
|
||||
}
|
||||
return arrayTuples.computeIfAbsent(
|
||||
new ArrayCacheKey( components ),
|
||||
|
|
Loading…
Reference in New Issue