tests for JPQL

tests for JPA operations
This commit is contained in:
Steve Ebersole 2020-08-31 18:31:51 -05:00
parent 076a0aa25a
commit ca1692b86f
68 changed files with 740 additions and 407 deletions

View File

@ -151,7 +151,7 @@ public interface MappingModelCreationLogger extends BasicLogger {
|90003501
|90004000
|org.hibernate.orm.query.hql
|org.hibernate.query.hql.HqlLogger
|org.hibernate.query.hql.HqlLogging
|90004001
|90005000

View File

@ -35,6 +35,9 @@ import org.hibernate.engine.spi.ExceptionConverter;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.loader.MultipleBagFetchException;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.InterpretationException;
import org.hibernate.query.sqm.ParsingException;
/**
* @author Andrea Boriero
@ -134,9 +137,18 @@ public class ExceptionConverterImpl implements ExceptionConverter {
handlePersistenceException( converted );
return converted;
}
else if ( cause instanceof SemanticException ) {
return new IllegalArgumentException( cause );
}
else if ( cause instanceof QueryException ) {
return new IllegalArgumentException( cause );
}
else if ( cause instanceof InterpretationException ) {
return new IllegalArgumentException( cause );
}
else if ( cause instanceof ParsingException ) {
return new IllegalArgumentException( cause );
}
else if ( cause instanceof MultipleBagFetchException ) {
return new IllegalArgumentException( cause );
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.internal.util;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
@ -43,6 +44,14 @@ public class MutableObject<T> {
this.reference = reference;
}
public void set(T reference, BiConsumer<T,T> existingConsumer) {
if ( this.reference != null ) {
existingConsumer.accept( reference, this.reference );
}
this.reference = reference;
}
public void setIfNot(T reference) {
if ( this.reference == null ) {
this.reference = reference;

View File

@ -13,6 +13,11 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
*/
public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValuedModelPart {
String ROLE_NAME = "{discriminator}";
String LEGACY_HQL_ROLE_NAME = "class";
static boolean matchesRoleName(String name) {
return ROLE_NAME.equals( name ) || LEGACY_HQL_ROLE_NAME.equals( name );
}
@Override
default String getPartName() {

View File

@ -15,6 +15,7 @@ import javax.persistence.metamodel.ManagedType;
import org.hibernate.Incubating;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.spi.TypeConfiguration;
@ -114,4 +115,6 @@ public interface JpaMetamodel extends javax.persistence.metamodel.Metamodel {
<T> RootGraphImplementor<T> findEntityGraphByName(String name);
<T> List<RootGraphImplementor<? super T>> findEntityGraphsByJavaType(Class<T> entityClass);
JpaCompliance getJpaCompliance();
}

View File

@ -7,11 +7,8 @@
package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath;
@ -35,17 +32,7 @@ public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> {
@Override
public SqmPathSource<?> findSubPathSource(String name) {
final EntityDomainType<J> sqmPathType = getSqmPathType();
final PersistentAttribute<?,?> attribute = sqmPathType.findAttribute( name );
if ( attribute != null ) {
return (SqmPathSource<?>) attribute;
}
final SingularPersistentAttribute<J, ?> idAttribute = sqmPathType.findIdAttribute();
if ( idAttribute != null && idAttribute.getName().equals( name ) ) {
return idAttribute;
}
throw new SemanticException( "Unknown sub-path name : " + name );
return sqmPathType.findSubPathSource( name );
}
@Override

View File

@ -12,15 +12,21 @@ import javax.persistence.metamodel.EntityType;
import org.hibernate.graph.internal.SubGraphImpl;
import org.hibernate.graph.spi.SubGraphImplementor;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.model.domain.AbstractIdentifiableType;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
@ -33,6 +39,7 @@ public class EntityTypeImpl<J>
extends AbstractIdentifiableType<J>
implements EntityDomainType<J>, Serializable {
private final String jpaEntityName;
private final SqmPathSource<?> discriminatorPathSource;
public EntityTypeImpl(
JavaTypeDescriptor<J> javaTypeDescriptor,
@ -50,6 +57,63 @@ public class EntityTypeImpl<J>
);
this.jpaEntityName = persistentClass.getJpaEntityName();
if ( persistentClass.hasSubclasses() ) {
final Value discriminator = persistentClass.getDiscriminator();
final DomainType discriminatorType;
if ( discriminator != null ) {
discriminatorType = (DomainType) discriminator.getType();
}
else {
discriminatorType = StandardBasicTypes.STRING;
}
discriminatorPathSource = new SqmPathSource() {
@Override
public String getPathName() {
return EntityDiscriminatorMapping.ROLE_NAME;
}
@Override
public DomainType<?> getSqmPathType() {
// the BasicType for Class?
return discriminatorType;
}
@Override
public SqmPathSource<?> findSubPathSource(String name) {
throw new IllegalPathUsageException( "Entity discriminator cannot be de-referenced" );
}
@Override
public SqmPath<?> createSqmPath(SqmPath lhs, SqmCreationState creationState) {
return new SqmBasicValuedSimplePath(
lhs.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ),
this,
lhs,
creationState.getCreationContext().getNodeBuilder()
);
}
@Override
public BindableType getBindableType() {
return BindableType.SINGULAR_ATTRIBUTE;
}
@Override
public Class<?> getBindableJavaType() {
return getExpressableJavaTypeDescriptor().getJavaType();
}
@Override
public JavaTypeDescriptor<?> getExpressableJavaTypeDescriptor() {
return discriminatorType.getExpressableJavaTypeDescriptor();
}
};
}
else {
discriminatorPathSource = null;
}
}
@Override
@ -83,6 +147,10 @@ public class EntityTypeImpl<J>
// todo (6.0) : probably need special handling here for non-aggregated composite ids
}
if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) {
return discriminatorPathSource;
}
return null;
}

View File

@ -36,9 +36,9 @@ import org.hibernate.internal.EntityManagerMessageLogger;
import org.hibernate.internal.HEMLogging;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.metamodel.internal.InflightRuntimeMetamodel;
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
import org.hibernate.metamodel.internal.MetadataContext;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
@ -71,6 +71,7 @@ public class JpaMetamodelImpl implements JpaMetamodel {
}
private final TypeConfiguration typeConfiguration;
private final JpaCompliance jpaCompliance;
private final Map<String, EntityDomainType<?>> jpaEntityTypeMap = new ConcurrentHashMap<>();
private final Map<Class<?>, MappedSuperclassDomainType<?>> jpaMappedSuperclassTypeMap = new ConcurrentHashMap<>();
@ -85,8 +86,9 @@ public class JpaMetamodelImpl implements JpaMetamodel {
private final Map<String, ImportInfo<?>> nameToImportMap = new ConcurrentHashMap<>();
public JpaMetamodelImpl(TypeConfiguration typeConfiguration) {
public JpaMetamodelImpl(TypeConfiguration typeConfiguration, JpaCompliance jpaCompliance) {
this.typeConfiguration = typeConfiguration;
this.jpaCompliance = jpaCompliance;
}
@Override
@ -94,6 +96,11 @@ public class JpaMetamodelImpl implements JpaMetamodel {
return typeConfiguration;
}
@Override
public JpaCompliance getJpaCompliance() {
return jpaCompliance;
}
@Override
public <X> EntityDomainType<X> entity(String entityName) {
//noinspection unchecked
@ -454,25 +461,6 @@ public class JpaMetamodelImpl implements JpaMetamodel {
throw new IllegalArgumentException( "Could not resolve entity reference : " + javaType.getName() );
}
public static JpaMetamodel buildMetamodel(
RuntimeModelCreationContext runtimeModelCreationContext,
MetadataImplementor bootMetamodel,
InflightRuntimeMetamodel inflightRuntimeMetamodel,
JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting,
java.util.Collection<NamedEntityGraphDefinition> namedEntityGraphDefinitions) {
final JpaMetamodelImpl jpaMetamodel = new JpaMetamodelImpl( inflightRuntimeMetamodel.getTypeConfiguration() );
jpaMetamodel.processJpa(
bootMetamodel,
inflightRuntimeMetamodel.getEntityProxyInterfaceMap(),
jpaStaticMetaModelPopulationSetting,
namedEntityGraphDefinitions,
runtimeModelCreationContext
);
return jpaMetamodel;
}
public void processJpa(
MetadataImplementor bootMetamodel,
Map<Class, String> entityProxyInterfaceMap,

View File

@ -149,7 +149,7 @@ public class MappingMetamodelImpl implements MappingMetamodel, MetamodelImplemen
public MappingMetamodelImpl(SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration) {
this.sessionFactory = sessionFactory;
this.typeConfiguration = typeConfiguration;
this.jpaMetamodel = new JpaMetamodelImpl( typeConfiguration );
this.jpaMetamodel = new JpaMetamodelImpl( typeConfiguration, sessionFactory.getSessionFactoryOptions().getJpaCompliance() );
}
public JpaMetamodel getJpaMetamodel() {

View File

@ -26,6 +26,7 @@ import javax.persistence.TemporalType;
import javax.persistence.TransactionRequiredException;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.ScrollMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -33,7 +34,6 @@ 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;
@ -54,6 +54,7 @@ import org.hibernate.query.results.ResultSetMapping;
import org.hibernate.query.results.ResultSetMappingImpl;
import org.hibernate.query.spi.AbstractQuery;
import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.result.NoMoreReturnsException;
@ -63,8 +64,6 @@ import org.hibernate.result.UpdateCountOutput;
import org.hibernate.result.spi.ResultContext;
import org.hibernate.sql.results.NoMoreOutputsException;
import org.jboss.logging.Logger;
/**
* Standard implementation of {@link org.hibernate.procedure.ProcedureCall}
*
@ -73,10 +72,6 @@ import org.jboss.logging.Logger;
public class ProcedureCallImpl<R>
extends AbstractQuery<R>
implements ProcedureCallImplementor<R>, ResultContext {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
ProcedureCallImpl.class.getName()
);
private final String procedureName;
@ -272,6 +267,11 @@ public class ProcedureCallImpl<R>
return queryOptions;
}
@Override
public QueryImplementor<R> setLockMode(String alias, LockMode lockMode) {
throw new IllegalStateException( "Cannot set LockMode on a procedure-call" );
}
@Override
public ProcedureParameterMetadataImpl getParameterMetadata() {
return parameterMetadata;
@ -601,21 +601,6 @@ public class ProcedureCallImpl<R>
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" );

View File

@ -24,10 +24,10 @@ import static org.jboss.logging.Logger.Level.ERROR;
*/
@MessageLogger( projectCode = "HHH" )
@ValidIdRange( min = 90003501, max = 90004000 )
public interface HqlLogger extends BasicLogger {
public interface HqlLogging extends BasicLogger {
String LOGGER_NAME = QueryLogging.subLoggerName( "hql" );
HqlLogger QUERY_LOGGER = Logger.getMessageLogger( HqlLogger.class, LOGGER_NAME );
HqlLogging QUERY_LOGGER = Logger.getMessageLogger( HqlLogging.class, LOGGER_NAME );
boolean TRACE_ENABLED = QUERY_LOGGER.isTraceEnabled();
boolean DEBUG_ENABLED = QUERY_LOGGER.isDebugEnabled();

View File

@ -9,18 +9,22 @@ package org.hibernate.query.hql.internal;
import java.lang.reflect.Field;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.DotIdentifierConsumer;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.ParsingException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -45,8 +49,6 @@ import org.jboss.logging.Logger;
* @author Steve Ebersole
*/
public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
private static final Logger log = Logger.getLogger( BasicDotIdentifierConsumer.class );
private final SqmCreationState creationState;
private String pathSoFar;
@ -84,7 +86,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
pathSoFar += ( '.' + identifier );
}
log.tracef(
HqlLogging.QUERY_LOGGER.tracef(
"BasicDotIdentifierHandler#consumeIdentifier( %s, %s, %s ) - %s",
identifier,
isBase,
@ -112,6 +114,14 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
String identifier,
boolean isTerminal,
SqmCreationState creationState) {
HqlLogging.QUERY_LOGGER.tracef(
"BaseLocalSequencePart#consumeIdentifier( %s, %s, %s ) - %s",
identifier,
isBase,
isTerminal,
pathSoFar
);
if ( isBase ) {
isBase = false;
@ -119,7 +129,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
.getCurrent()
.getPathRegistry();
final SqmFrom pathRootByAlias = sqmPathRegistry.findFromByAlias( identifier );
final SqmFrom<?,?> pathRootByAlias = sqmPathRegistry.findFromByAlias( identifier );
if ( pathRootByAlias != null ) {
// identifier is an alias (identification variable)
validateAsRoot( pathRootByAlias );
@ -144,7 +154,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
}
else {
pathRootByExposedNavigable.registerImplicitJoinPath( sqmPath );
return new DomainPathPart( pathRootByAlias );
return new DomainPathPart( pathRootByExposedNavigable );
}
}
}
@ -161,11 +171,19 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
//
// todo (6.0) : finish this logic. and see above note in `! isTerminal` block
if ( !isTerminal ) {
final SqmCreationContext creationContext = creationState.getCreationContext();
if ( ! isTerminal ) {
return this;
}
final SqmCreationContext creationContext = creationState.getCreationContext();
final String importableName = creationContext.getJpaMetamodel().qualifyImportableName( pathSoFar );
if ( importableName != null ) {
final EntityDomainType<?> entityDomainType = creationContext.getJpaMetamodel().entity( importableName );
if ( entityDomainType != null ) {
return new SqmLiteralEntityType( entityDomainType, creationContext.getNodeBuilder() );
}
}
final SqmFunctionDescriptor functionDescriptor = creationContext.getQueryEngine()
.getSqmFunctionRegistry()

View File

@ -8,6 +8,7 @@ package org.hibernate.query.hql.internal;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState;
@ -25,6 +26,7 @@ public class DomainPathPart implements SemanticPathPart {
@SuppressWarnings("WeakerAccess")
public DomainPathPart(SqmPath<?> basePath) {
this.currentPath = basePath;
assert currentPath != null;
}
@Override
@ -32,6 +34,11 @@ public class DomainPathPart implements SemanticPathPart {
String name,
boolean isTerminal,
SqmCreationState creationState) {
HqlLogging.QUERY_LOGGER.tracef(
"Resolving DomainPathPart(%s) sub-part : %s",
currentPath,
name
);
final SqmPath<?> lhs = currentPath;
final SqmPathSource subPathSource = lhs.getReferencedPathSource().findSubPathSource( name );
if ( subPathSource == null ) {

View File

@ -8,7 +8,7 @@ package org.hibernate.query.hql.internal;
import org.hibernate.grammars.hql.HqlLexer;
import org.hibernate.grammars.hql.HqlParser;
import org.hibernate.query.hql.HqlLogger;
import org.hibernate.query.hql.HqlLogging;
import org.jboss.logging.Logger;
@ -22,7 +22,7 @@ import org.antlr.v4.runtime.Token;
* @author Steve Ebersole
*/
public class HqlParseTreeBuilder {
private static final Logger LOGGER = HqlLogger.subLogger( "reservedWordAsIdentifier" );
private static final Logger LOGGER = HqlLogging.subLogger( "reservedWordAsIdentifier" );
private static final boolean DEBUG_ENABLED = LOGGER.isDebugEnabled();
/**

View File

@ -474,7 +474,7 @@ public class QuerySplitter {
@Override
public SqmEmptinessPredicate visitIsEmptyPredicate(SqmEmptinessPredicate predicate) {
return new SqmEmptinessPredicate(
(SqmPath) predicate.getPluralPath().accept( this ),
(SqmPluralValuedSimplePath<?>) predicate.getPluralPath().accept( this ),
predicate.isNegated(),
predicate.nodeBuilder()
);
@ -483,7 +483,7 @@ public class QuerySplitter {
@Override
public SqmNullnessPredicate visitIsNullPredicate(SqmNullnessPredicate predicate) {
return new SqmNullnessPredicate(
(SqmExpression) predicate.getExpression().accept( this ),
(SqmExpression<?>) predicate.getExpression().accept( this ),
predicate.isNegated(),
predicate.nodeBuilder()
);
@ -492,9 +492,9 @@ public class QuerySplitter {
@Override
public SqmBetweenPredicate visitBetweenPredicate(SqmBetweenPredicate predicate) {
return new SqmBetweenPredicate(
(SqmExpression) predicate.getExpression().accept( this ),
(SqmExpression) predicate.getLowerBound().accept( this ),
(SqmExpression) predicate.getUpperBound().accept( this ),
(SqmExpression<?>) predicate.getExpression().accept( this ),
(SqmExpression<?>) predicate.getLowerBound().accept( this ),
(SqmExpression<?>) predicate.getUpperBound().accept( this ),
predicate.isNegated(),
predicate.nodeBuilder()
);
@ -503,9 +503,9 @@ public class QuerySplitter {
@Override
public SqmLikePredicate visitLikePredicate(SqmLikePredicate predicate) {
return new SqmLikePredicate(
(SqmExpression) predicate.getMatchExpression().accept( this ),
(SqmExpression) predicate.getPattern().accept( this ),
(SqmExpression) predicate.getEscapeCharacter().accept( this ),
(SqmExpression<?>) predicate.getMatchExpression().accept( this ),
(SqmExpression<?>) predicate.getPattern().accept( this ),
(SqmExpression<?>) predicate.getEscapeCharacter().accept( this ),
predicate.nodeBuilder()
);
}

View File

@ -30,7 +30,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.NullPrecedence;
import org.hibernate.QueryException;
@ -58,7 +57,7 @@ import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.TrimSpec;
import org.hibernate.query.UnaryArithmeticOperator;
import org.hibernate.query.hql.HqlLogger;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.DotIdentifierConsumer;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationOptions;
@ -76,6 +75,7 @@ import org.hibernate.query.sqm.UnknownEntityException;
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.internal.ParameterCollector;
import org.hibernate.query.sqm.internal.SqmCreationProcessingStateImpl;
import org.hibernate.query.sqm.internal.SqmDmlCreationProcessingState;
import org.hibernate.query.sqm.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
@ -92,6 +92,7 @@ import org.hibernate.query.sqm.tree.domain.SqmMaxIndexPath;
import org.hibernate.query.sqm.tree.domain.SqmMinElementPath;
import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.query.sqm.tree.expression.SqmAny;
@ -164,6 +165,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.jboss.logging.Logger;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TerminalNode;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME;
@ -171,7 +173,17 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.hibernate.grammars.hql.HqlParser.IDENTIFIER;
import static org.hibernate.query.TemporalUnit.*;
import static org.hibernate.query.TemporalUnit.DATE;
import static org.hibernate.query.TemporalUnit.DAY_OF_MONTH;
import static org.hibernate.query.TemporalUnit.DAY_OF_WEEK;
import static org.hibernate.query.TemporalUnit.DAY_OF_YEAR;
import static org.hibernate.query.TemporalUnit.NANOSECOND;
import static org.hibernate.query.TemporalUnit.OFFSET;
import static org.hibernate.query.TemporalUnit.TIME;
import static org.hibernate.query.TemporalUnit.TIMEZONE_HOUR;
import static org.hibernate.query.TemporalUnit.TIMEZONE_MINUTE;
import static org.hibernate.query.TemporalUnit.WEEK_OF_MONTH;
import static org.hibernate.query.TemporalUnit.WEEK_OF_YEAR;
import static org.hibernate.type.descriptor.DateTimeUtils.DATE_TIME;
import static org.hibernate.type.spi.TypeConfiguration.isJdbcTemporalType;
@ -310,7 +322,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
final SqmRoot<?> root = new SqmRoot<>(
visitEntityName( ctx.dmlTarget().entityName() ),
visitIdentificationVariableDef( ctx.dmlTarget().identificationVariableDef() ),
applyJpaCompliance( visitIdentificationVariableDef( ctx.dmlTarget().identificationVariableDef() ) ),
creationContext.getNodeBuilder()
);
@ -323,15 +335,26 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
);
processingStateStack.push( processingState );
processingState.getPathRegistry().register( root );
try {
insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) );
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.targetFieldsSpec().dotIdentifierSequence() ) {
final SqmPath stateField = (SqmPath) visitDotIdentifierSequence( stateFieldCtx );
// todo : validate each resolved stateField...
insertStatement.addInsertTargetStateField( stateField );
final SqmCreationProcessingState stateFieldsProcessingState = new SqmCreationProcessingStateImpl(
insertStatement,
this
);
stateFieldsProcessingState.getPathRegistry().register( root );
processingStateStack.push( stateFieldsProcessingState );
try {
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.targetFieldsSpec().dotIdentifierSequence() ) {
final SqmPath stateField = (SqmPath) visitDotIdentifierSequence( stateFieldCtx );
// todo : validate each resolved stateField...
insertStatement.addInsertTargetStateField( stateField );
}
}
finally {
processingStateStack.pop();
}
return insertStatement;
@ -560,7 +583,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
@Override
public SqmSelection visitSelection(HqlParser.SelectionContext ctx) {
final String resultIdentifier = visitResultIdentifier( ctx.resultIdentifier() );
final String resultIdentifier = applyJpaCompliance( visitResultIdentifier( ctx.resultIdentifier() ) );
final SqmSelectableNode selectableNode = visitSelectableNode( ctx );
//noinspection unchecked
@ -746,7 +769,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
}
if ( sortExpression instanceof SqmLiteral
|| sortExpression instanceof SqmParameter ) {
HqlLogger.QUERY_LOGGER.debugf( "Questionable sorting by constant value : %s", sortExpression );
HqlLogging.QUERY_LOGGER.debugf( "Questionable sorting by constant value : %s", sortExpression );
}
final String collation;
@ -903,8 +926,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
final SqmFromClause fromClause = new SqmFromClause( parserFromClause==null ? 0 : parserFromClause.fromClauseSpace().size() );
if ( parserFromClause!=null ) {
for ( HqlParser.FromClauseSpaceContext parserSpace : parserFromClause.fromClauseSpace() ) {
final SqmRoot sqmPathRoot = visitFromClauseSpace(parserSpace);
fromClause.addRoot(sqmPathRoot);
final SqmRoot sqmPathRoot = visitFromClauseSpace( parserSpace );
fromClause.addRoot( sqmPathRoot );
}
}
return fromClause;
@ -935,14 +958,15 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
}
@Override
@SuppressWarnings( { "rawtypes", "unchecked" } )
public SqmRoot visitPathRoot(HqlParser.PathRootContext ctx) {
final String name = ctx.entityName().fullNameText;
log.debugf( "Handling root path - %s", name );
final EntityDomainType entityDescriptor = getCreationContext().getJpaMetamodel().resolveHqlEntityReference(
name
);
final EntityDomainType entityDescriptor = getCreationContext()
.getJpaMetamodel()
.resolveHqlEntityReference( name );
checkFQNEntityNameJpaComplianceViolationIfNeeded( name, entityDescriptor );
@ -962,15 +986,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
}
}
final String alias = visitIdentificationVariableDef( ctx.identificationVariableDef() );
//noinspection unchecked
final SqmRoot sqmRoot = new SqmRoot(
entityDescriptor,
alias,
creationContext.getNodeBuilder()
final String alias = applyJpaCompliance(
visitIdentificationVariableDef( ctx.identificationVariableDef() )
);
final SqmRoot sqmRoot = new SqmRoot( entityDescriptor, alias, creationContext.getNodeBuilder() );
processingStateStack.getCurrent().getPathRegistry().register( sqmRoot );
return sqmRoot;
@ -1009,6 +1030,18 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
return null;
}
private String applyJpaCompliance(String text) {
if ( text == null ) {
return null;
}
if ( getCreationOptions().useStrictJpaCompliance() ) {
return text.toLowerCase( Locale.getDefault() );
}
return text;
}
@Override
public final SqmCrossJoin visitCrossJoin(HqlParser.CrossJoinContext ctx) {
throw new UnsupportedOperationException( "Unexpected call to #visitCrossJoin, see #consumeCrossJoin" );
@ -1217,7 +1250,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
@Override
public SqmEmptinessPredicate visitIsEmptyPredicate(HqlParser.IsEmptyPredicateContext ctx) {
return new SqmEmptinessPredicate(
(SqmPath) ctx.expression().accept( this ),
(SqmPluralValuedSimplePath<?>) ctx.expression().accept( this ),
ctx.NOT() != null,
creationContext.getNodeBuilder()
);

View File

@ -12,8 +12,9 @@ import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.hql.HqlLogger;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.AliasCollisionException;
@ -31,6 +32,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelection;
*/
public class SqmPathRegistryImpl implements SqmPathRegistry {
private final SqmCreationProcessingState associatedProcessingState;
private final JpaCompliance jpaCompliance;
private final Map<NavigablePath, SqmPath> sqmPathByPath = new HashMap<>();
private final Map<NavigablePath, SqmFrom> sqmFromByPath = new HashMap<>();
@ -41,6 +43,7 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
public SqmPathRegistryImpl(SqmCreationProcessingState associatedProcessingState) {
this.associatedProcessingState = associatedProcessingState;
this.jpaCompliance = associatedProcessingState.getCreationState().getCreationContext().getJpaMetamodel().getJpaCompliance();
}
@Override
@ -60,7 +63,12 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
final String alias = sqmPath.getExplicitAlias();
if ( alias != null ) {
final SqmFrom previousFrom = sqmFromByAlias.put( alias, sqmFrom );
final String aliasToUse = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;
final SqmFrom previousFrom = sqmFromByAlias.put( aliasToUse, sqmFrom );
if ( previousFrom != null ) {
throw new AliasCollisionException(
String.format(
@ -148,7 +156,12 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
@Override
public SqmFrom findFromByAlias(String alias) {
final SqmFrom registered = sqmFromByAlias.get( alias );
final String localAlias = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;
final SqmFrom registered = sqmFromByAlias.get( localAlias );
if ( registered != null ) {
return registered;
}
@ -167,10 +180,11 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
// (configurable?) option would be to simply pick the first one as a perf optimization
SqmFrom found = null;
for ( SqmFrom fromElement : sqmFromByPath.values() ) {
for ( Map.Entry<NavigablePath, SqmFrom> entry : sqmFromByPath.entrySet() ) {
final SqmFrom fromElement = entry.getValue();
if ( definesAttribute( fromElement.getReferencedPathSource(), navigableName ) ) {
if ( found != null ) {
// throw new IllegalStateException( "Multiple from-elements expose unqualified attribute : " + navigableName );
throw new IllegalStateException( "Multiple from-elements expose unqualified attribute : " + navigableName );
}
found = fromElement;
}
@ -178,7 +192,7 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
if ( found == null ) {
if ( associatedProcessingState.getParentProcessingState() != null ) {
HqlLogger.QUERY_LOGGER.debugf(
HqlLogging.QUERY_LOGGER.debugf(
"Unable to resolve unqualified attribute [%s] in local from-clause; checking parent ",
navigableName
);
@ -186,6 +200,11 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
}
}
HqlLogging.QUERY_LOGGER.debugf(
"Unable to resolve unqualified attribute [%s] in local from-clause",
navigableName
);
return found;
}

View File

@ -9,7 +9,7 @@ package org.hibernate.query.hql.internal;
import org.hibernate.QueryException;
import org.hibernate.grammars.hql.HqlLexer;
import org.hibernate.grammars.hql.HqlParser;
import org.hibernate.query.hql.HqlLogger;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.sqm.InterpretationException;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.internal.SqmTreePrinter;
@ -42,7 +42,7 @@ public class StandardHqlTranslator implements HqlTranslator {
@Override
public SqmStatement translate(String query) {
HqlLogger.QUERY_LOGGER.debugf( "HQL : " + query );
HqlLogging.QUERY_LOGGER.debugf( "HQL : " + query );
final HqlParser.StatementContext hqlParseTree = parseHql( query );

View File

@ -89,5 +89,4 @@ public interface SqmPathRegistry {
* Find an SqmSelection by its position in the SqmSelectClause
*/
SqmSelection findSelectionByPosition(int position);
}

View File

@ -7,6 +7,7 @@
package org.hibernate.query.results;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -50,6 +51,10 @@ public class ResultSetMappingImpl implements ResultSetMapping {
return resultBuilders == null ? 0 : resultBuilders.size();
}
public List<ResultBuilder> getResultBuilders() {
return Collections.unmodifiableList( resultBuilders );
}
@Override
public void visitResultBuilders(BiConsumer<Integer, ResultBuilder> resultBuilderConsumer) {
if ( resultBuilders == null ) {

View File

@ -10,6 +10,7 @@ import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlExpressionAccess;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.descriptor.ValueExtractor;
@ -22,7 +23,7 @@ import org.hibernate.type.spi.TypeConfiguration;
*
* @author Steve Ebersole
*/
public class SqlSelectionImpl implements SqlSelection, Expression {
public class SqlSelectionImpl implements SqlSelection, Expression, SqlExpressionAccess {
private final int valuesArrayPosition;
private final BasicValuedMapping valueMapping;
private final JdbcMapping jdbcMapping;
@ -68,4 +69,9 @@ public class SqlSelectionImpl implements SqlSelection, Expression {
public void accept(SqlAstWalker sqlAstWalker) {
throw new UnsupportedOperationException();
}
@Override
public Expression getSqlExpression() {
return this;
}
}

View File

@ -58,6 +58,7 @@ import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.IllegalQueryOperationException;
import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer;
@ -67,6 +68,9 @@ import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import static org.hibernate.LockMode.UPGRADE;
import static org.hibernate.LockOptions.NONE;
import static org.hibernate.LockOptions.READ;
import static org.hibernate.LockOptions.WAIT_FOREVER;
import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE;
import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT;
@ -143,12 +147,6 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return session;
}
protected abstract boolean canApplyAliasSpecificLockModes();
protected abstract void verifySettingLockMode();
protected abstract void verifySettingAliasSpecificLockModes();
protected abstract QueryParameterBindings getQueryParameterBindings();
@Override
@ -164,27 +162,44 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public int getMaxResults() {
getSession().checkOpen();
return getQueryOptions().getLimit().getMaxRowsJpa();
}
@Override
public QueryImplementor<R> setMaxResults(int maxResult) {
if ( maxResult < 0 ) {
throw new IllegalArgumentException( "max-results cannot be negative" );
}
getSession().checkOpen();
getQueryOptions().getLimit().setMaxRows( maxResult );
return this;
}
@Override
public int getFirstResult() {
getSession().checkOpen();
return getQueryOptions().getLimit().getFirstRowJpa();
}
@Override
public QueryImplementor<R> setFirstResult(int startPosition) {
getSession().checkOpen();
if ( startPosition < 0 ) {
throw new IllegalArgumentException( "first-result value cannot be negative : " + startPosition );
}
getQueryOptions().getLimit().setFirstRow( startPosition );
return this;
}
@Override
@SuppressWarnings( "rawtypes" )
public QueryImplementor<R> setTupleTransformer(TupleTransformer transformer) {
getQueryOptions().setTupleTransformer( transformer );
return this;
@ -196,25 +211,20 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return this;
}
@Override
public LockModeType getLockMode() {
return LockModeTypeHelper.getLockModeType( getQueryOptions().getLockOptions().getLockMode() );
}
@Override
public FlushMode getHibernateFlushMode() {
return getQueryOptions().getFlushMode();
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setHibernateFlushMode(FlushMode flushMode) {
public QueryImplementor<R> setHibernateFlushMode(FlushMode flushMode) {
getQueryOptions().setFlushMode( flushMode );
return this;
}
@Override
public FlushModeType getFlushMode() {
getSession().checkOpen();
final FlushMode flushMode = getQueryOptions().getFlushMode() == null
? getSession().getHibernateFlushMode()
: getQueryOptions().getFlushMode();
@ -222,8 +232,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setFlushMode(FlushModeType flushModeType) {
public QueryImplementor<R> setFlushMode(FlushModeType flushModeType) {
getSession().checkOpen();
setHibernateFlushMode( FlushModeTypeHelper.getFlushMode( flushModeType ) );
return this;
}
@ -234,8 +244,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setCacheMode(CacheMode cacheMode) {
public QueryImplementor<R> setCacheMode(CacheMode cacheMode) {
getQueryOptions().setCacheMode( cacheMode );
return this;
}
@ -246,8 +255,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setCacheable(boolean cacheable) {
public QueryImplementor<R> setCacheable(boolean cacheable) {
getQueryOptions().setResultCachingEnabled( cacheable );
return this;
}
@ -258,8 +266,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setCacheRegion(String cacheRegion) {
public QueryImplementor<R> setCacheRegion(String cacheRegion) {
getQueryOptions().setResultCacheRegionName( cacheRegion );
return this;
}
@ -270,8 +277,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setTimeout(int timeout) {
public QueryImplementor<R> setTimeout(int timeout) {
getQueryOptions().setTimeout( timeout );
return this;
}
@ -282,8 +288,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setFetchSize(int fetchSize) {
public QueryImplementor<R> setFetchSize(int fetchSize) {
getQueryOptions().setFetchSize( fetchSize );
return this;
}
@ -296,8 +301,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setReadOnly(boolean readOnly) {
public QueryImplementor<R> setReadOnly(boolean readOnly) {
getQueryOptions().setReadOnly( readOnly );
return this;
}
@ -308,8 +312,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setLockOptions(LockOptions lockOptions) {
public LockModeType getLockMode() {
getSession().checkOpen( false );
return LockModeTypeHelper.getLockModeType( getQueryOptions().getLockOptions().getLockMode() );
}
@Override
public QueryImplementor<R> setLockOptions(LockOptions lockOptions) {
getQueryOptions().getLockOptions().setLockMode( lockOptions.getLockMode() );
getQueryOptions().getLockOptions().setScope( lockOptions.getScope() );
getQueryOptions().getLockOptions().setTimeOut( lockOptions.getTimeOut() );
@ -318,23 +328,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setLockMode(String alias, LockMode lockMode) {
if ( !LockMode.NONE.equals( lockMode ) ) {
verifySettingAliasSpecificLockModes();
}
public QueryImplementor<R> setLockMode(String alias, LockMode lockMode) {
getQueryOptions().getLockOptions().setAliasSpecificLockMode( alias, lockMode );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setLockMode(LockModeType lockModeType) {
if ( !LockModeType.NONE.equals( lockModeType ) ) {
verifySettingLockMode();
}
public QueryImplementor<R> setLockMode(LockModeType lockModeType) {
getSession().checkOpen();
getQueryOptions().getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
return this;
}
@ -345,15 +346,13 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setComment(String comment) {
public QueryImplementor<R> setComment(String comment) {
getQueryOptions().setComment( comment );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor addQueryHint(String hint) {
public QueryImplementor<R> addQueryHint(String hint) {
getQueryOptions().addDatabaseHint( hint );
return this;
}
@ -375,16 +374,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
getSession().checkOpen( false );
final Map<String,Object> hints = new HashMap<>();
collectBaselineHints( hints );
collectHints( hints );
return hints;
}
@SuppressWarnings("WeakerAccess")
protected void collectBaselineHints(Map<String, Object> hints) {
// nothing to do in this form
}
protected void collectHints(Map<String, Object> hints) {
if ( getQueryOptions().getTimeout() != null ) {
hints.put( HINT_TIMEOUT, getQueryOptions().getTimeout() );
@ -428,7 +421,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
}
protected void putIfNotNull(Map<String, Object> hints, String hintName, Enum hintValue) {
protected void putIfNotNull(Map<String, Object> hints, String hintName, Enum<?> hintValue) {
// centralized spot to handle the decision whether to put enums directly into the hints map
// or whether to put the enum name
if ( hintValue != null ) {
@ -446,6 +439,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public QueryImplementor<R> setHint(String hintName, Object value) {
getSession().checkOpen( true );
boolean applied = false;
try {
if ( HINT_TIMEOUT.equals( hintName ) ) {
@ -492,27 +486,22 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
applied = applyNativeQueryLockMode( value );
}
else if ( hintName.startsWith( ALIAS_SPECIFIC_LOCK_MODE ) ) {
if ( canApplyAliasSpecificLockModes() ) {
// extract the alias
final String alias = hintName.substring( ALIAS_SPECIFIC_LOCK_MODE.length() + 1 );
// determine the LockMode
try {
final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value );
applyAliasSpecificLockModeHint( alias, lockMode );
}
catch ( Exception e ) {
log.unableToDetermineLockModeValue( hintName, value );
applied = false;
}
// extract the alias
final String alias = hintName.substring( ALIAS_SPECIFIC_LOCK_MODE.length() + 1 );
// determine the LockMode
try {
final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value );
applyAliasSpecificLockModeHint( alias, lockMode );
applied = true;
}
else {
//noinspection ConstantConditions
catch ( Exception e ) {
log.unableToDetermineLockModeValue( hintName, value );
applied = false;
}
}
else if ( HINT_FETCHGRAPH.equals( hintName ) || HINT_LOADGRAPH.equals( hintName ) ) {
if (value instanceof RootGraphImplementor ) {
applyEntityGraphQueryHint( hintName, (RootGraphImplementor) value );
applyEntityGraphQueryHint( hintName, (RootGraphImplementor<?>) value );
}
else {
log.warnf( "The %s hint was set, but the value was not an EntityGraph!", hintName );
@ -682,29 +671,34 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return true;
}
@SuppressWarnings( "UnusedReturnValue" )
protected boolean applyLockModeTypeHint(LockModeType lockModeType) {
getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
return true;
}
@SuppressWarnings( "UnusedReturnValue" )
protected boolean applyHibernateLockModeHint(LockMode lockMode) {
getLockOptions().setLockMode( lockMode );
final LockOptions lockOptions;
if ( lockMode == LockMode.NONE ) {
lockOptions = NONE;
}
else if ( lockMode == LockMode.READ ) {
lockOptions = READ;
}
else if ( lockMode == UPGRADE || lockMode == LockMode.PESSIMISTIC_WRITE ) {
lockOptions = LockOptions.UPGRADE;
}
return true;
}
/**
* Apply the alias specific lock modes. Assumes {@link #canApplyAliasSpecificLockModes()} has already been
* called and returned {@code true}.
*
* @param alias The alias to apply the 'lockMode' to.
* @param lockMode The LockMode to apply.
*/
@SuppressWarnings("WeakerAccess")
protected void applyAliasSpecificLockModeHint(String alias, LockMode lockMode) {
getLockOptions().setAliasSpecificLockMode( alias, lockMode );
setLockMode( alias, lockMode );
}
protected abstract void applyEntityGraphQueryHint(String hintName, RootGraphImplementor entityGraph);
protected abstract void applyEntityGraphQueryHint(String hintName, RootGraphImplementor<?> entityGraph);
/**
* Apply the follow-on-locking hint.
@ -719,19 +713,20 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// QueryParameter handling
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public Set<Parameter<?>> getParameters() {
getSession().checkOpen( false );
return (Set) ( (ParameterMetadata) getParameterMetadata() ).getRegistrations();
}
@Override
public Parameter<?> getParameter(String name) {
getSession().checkOpen( false );
try {
return getParameterMetadata().getQueryParameter( name );
}
@ -743,7 +738,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
@SuppressWarnings("unchecked")
public <T> Parameter<T> getParameter(String name, Class<T> type) {
getSession().checkOpen( false );
try {
//noinspection rawtypes
final QueryParameter parameter = getParameterMetadata().getQueryParameter( name );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
throw new IllegalArgumentException(
@ -761,6 +759,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public Parameter<?> getParameter(int position) {
getSession().checkOpen( false );
try {
return getParameterMetadata().getQueryParameter( position );
}
@ -770,8 +770,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public <T> Parameter<T> getParameter(int position, Class<T> type) {
getSession().checkOpen( false );
try {
final QueryParameter parameter = getParameterMetadata().getQueryParameter( position );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
@ -790,14 +792,15 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public boolean isBound(Parameter<?> param) {
final QueryParameterImplementor qp = getParameterMetadata().resolve( param );
getSession().checkOpen();
final QueryParameterImplementor<?> qp = getParameterMetadata().resolve( param );
return qp != null && getQueryParameterBindings().isBound( qp );
}
@SuppressWarnings("WeakerAccess")
@SuppressWarnings( {"WeakerAccess", "unchecked", "rawtypes"} )
protected <P> QueryParameterBinding<P> locateBinding(Parameter<P> parameter) {
if ( parameter instanceof QueryParameterImplementor ) {
//noinspection unchecked
return locateBinding( (QueryParameterImplementor) parameter );
}
else if ( parameter.getName() != null ) {
@ -814,20 +817,20 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@SuppressWarnings("WeakerAccess")
protected <P> QueryParameterBinding<P> locateBinding(QueryParameterImplementor<P> parameter) {
//noinspection unchecked
getSession().checkOpen();
return getQueryParameterBindings().getBinding( parameter );
}
@SuppressWarnings("WeakerAccess")
@SuppressWarnings( {"WeakerAccess", "unchecked"} )
protected <P> QueryParameterBinding<P> locateBinding(String name) {
//noinspection unchecked
return (QueryParameterBinding) getQueryParameterBindings().getBinding( name );
getSession().checkOpen();
return (QueryParameterBinding<P>) getQueryParameterBindings().getBinding( name );
}
@SuppressWarnings("WeakerAccess")
@SuppressWarnings( {"WeakerAccess", "unchecked"} )
protected <P> QueryParameterBinding<P> locateBinding(int position) {
//noinspection unchecked
return (QueryParameterBinding) getQueryParameterBindings().getBinding( position );
getSession().checkOpen();
return (QueryParameterBinding<P>) getQueryParameterBindings().getBinding( position );
}
@Override
@ -920,7 +923,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return this;
}
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
private <P> void setParameter(Parameter<P> parameter, Object value, AllowableParameterType type) {
if ( parameter instanceof QueryParameter ) {
setParameter( (QueryParameter) parameter, value, type );
@ -943,6 +946,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
setParameter( name, typedValueWrapper.getValue(), typedValueWrapper.getType() );
}
else if ( value instanceof Collection ) {
//noinspection rawtypes
setParameterList( name, (Collection) value );
}
else {
@ -958,7 +962,9 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
final TypedParameterValue typedParameterValue = (TypedParameterValue) value;
setParameter( position, typedParameterValue.getValue(), typedParameterValue.getType() );
}
if ( value instanceof Collection ) {
//noinspection rawtypes
setParameterList( Integer.toString( position ), (Collection) value );
}
else {
@ -968,21 +974,21 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public <P> QueryImplementor<R> setParameter(QueryParameter<P> parameter, P value, AllowableParameterType type) {
locateBinding( parameter ).setBindValue( value, type );
return this;
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(String name, Object value, AllowableParameterType type) {
locateBinding( name ).setBindValue( value, type );
return this;
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor setParameter(int position, Object value, AllowableParameterType type) {
locateBinding( position ).setBindValue( value, type );
return this;
@ -1012,29 +1018,29 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return this;
}
@SuppressWarnings("unchecked")
@Override
public QueryImplementor setParameterList(String name, Collection values) {
@SuppressWarnings( {"rawtypes", "unchecked"} )
public QueryImplementor<R> setParameterList(String name, Collection values) {
locateBinding( name ).setBindValues( values );
return this;
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values) {
locateBinding( position ).setBindValues( values );
return this;
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Collection values, AllowableParameterType type) {
locateBinding( name ).setBindValues( values, type );
return this;
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values, AllowableParameterType type) {
locateBinding( position ).setBindValues( values, type );
return this;
@ -1053,21 +1059,21 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType type) {
locateBinding( name ).setBindValues( Arrays.asList( values ), type );
return this;
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType type) {
locateBinding( position ).setBindValues( Arrays.asList( values ), type );
return this;
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Collection values, Class javaType) {
final JavaTypeDescriptor javaDescriptor = getSession().getFactory()
.getTypeConfiguration()
@ -1102,7 +1108,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values, Class javaType) {
final JavaTypeDescriptor javaDescriptor = getSession().getFactory()
.getTypeConfiguration()
@ -1137,14 +1143,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
locateBinding( (QueryParameter) param ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
locateBinding( (QueryParameter) param ).setBindValue( value, temporalType );
return this;
@ -1175,8 +1181,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public <T> T getParameterValue(Parameter<T> param) {
QueryLogging.QUERY_LOGGER.tracef( "#getParameterValue(%s)", param );
final QueryParameterImplementor qp = getParameterMetadata().resolve( param );
if ( qp == null ) {
throw new IllegalArgumentException( "The parameter [" + param + "] is not part of this Query" );
@ -1184,7 +1192,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( qp );
if ( binding == null || !binding.isBound() ) {
throw new IllegalStateException( "The parameter [" + param + "] has not yet been bound" );
throw new IllegalStateException( "Parameter value not yet bound : " + param.toString() );
}
if ( binding.isMultiValued() ) {
@ -1197,14 +1205,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public Object getParameterValue(String name) {
final QueryParameterImplementor qp = getParameterMetadata().getQueryParameter( name );
if ( qp == null ) {
throw new IllegalArgumentException( "The parameter [" + name + "] is not part of this Query" );
final QueryParameterImplementor<?> parameter = getParameterMetadata().getQueryParameter( name );
if ( parameter == null ) {
throw new IllegalArgumentException( "Could not resolve parameter by name - " + name );
}
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( qp );
final QueryParameterBinding<?> binding = getQueryParameterBindings().getBinding( parameter );
if ( binding == null || !binding.isBound() ) {
throw new IllegalStateException( "The parameter [" + name + "] has not yet been bound" );
throw new IllegalStateException( "Parameter value not yet bound : " + parameter.toString() );
}
if ( binding.isMultiValued() ) {
@ -1217,12 +1225,12 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public Object getParameterValue(int position) {
final QueryParameterImplementor qp = getParameterMetadata().getQueryParameter( position );
if ( qp == null ) {
throw new IllegalArgumentException( "The parameter [" + position + "] is not part of this Query" );
final QueryParameterImplementor<?> parameter = getParameterMetadata().getQueryParameter( position );
if ( parameter == null ) {
throw new IllegalArgumentException( "Could not resolve parameter by position - " + position );
}
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( qp );
final QueryParameterBinding<?> binding = getQueryParameterBindings().getBinding( parameter );
if ( binding == null || !binding.isBound() ) {
throw new IllegalStateException( "The parameter [" + position + "] has not yet been bound" );
}
@ -1271,7 +1279,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public QueryImplementor<R> setProperties(Object bean) {
Class clazz = bean.getClass();
final Class<?> clazz = bean.getClass();
for ( String paramName : getParameterMetadata().getNamedParameterNames() ) {
try {
final PropertyAccess propertyAccess = BuiltInPropertyAccessStrategies.BASIC.getStrategy().buildPropertyAccess(
@ -1279,16 +1287,16 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
paramName
);
final Getter getter = propertyAccess.getGetter();
final Class retType = getter.getReturnType();
final Class<?> retType = getter.getReturnType();
final Object object = getter.get( bean );
if ( Collection.class.isAssignableFrom( retType ) ) {
setParameterList( paramName, (Collection) object );
setParameterList( paramName, (Collection<?>) object );
}
else if ( retType.isArray() ) {
setParameterList( paramName, (Object[]) object );
}
else {
AllowableParameterType type = determineType( paramName, retType );
AllowableParameterType<?> type = determineType( paramName, retType );
setParameter( paramName, object, type );
}
}
@ -1300,8 +1308,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@SuppressWarnings("WeakerAccess")
protected AllowableParameterType determineType(String namedParam, Class retType) {
AllowableParameterType type = locateBinding( namedParam ).getBindType();
protected AllowableParameterType<?> determineType(String namedParam, Class<?> retType) {
AllowableParameterType<?> type = locateBinding( namedParam ).getBindType();
if ( type == null ) {
type = getParameterMetadata().getQueryParameter( namedParam ).getHibernateType();
}
@ -1312,8 +1320,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setProperties(Map map) {
@SuppressWarnings( "rawtypes" )
public QueryImplementor<R> setProperties(Map map) {
for ( String paramName : getParameterMetadata().getNamedParameterNames() ) {
final Object object = map.get( paramName );
if ( object == null ) {
@ -1417,12 +1425,12 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
public ScrollableResultsImplementor scroll() {
public ScrollableResultsImplementor<?> scroll() {
return scroll( getSession().getFactory().getJdbcServices().getJdbcEnvironment().getDialect().defaultScrollMode() );
}
@Override
public ScrollableResultsImplementor scroll(ScrollMode scrollMode) {
public ScrollableResultsImplementor<?> scroll(ScrollMode scrollMode) {
beforeQuery( false );
try {
return doScroll( scrollMode );
@ -1432,10 +1440,10 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
}
protected abstract ScrollableResultsImplementor doScroll(ScrollMode scrollMode);
protected abstract ScrollableResultsImplementor<?> doScroll(ScrollMode scrollMode);
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings( {"unchecked", "rawtypes"} )
public Stream<R> stream() {
final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY );
final ScrollableResultsIterator<R> iterator = new ScrollableResultsIterator<>( scrollableResults );

View File

@ -0,0 +1,21 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query.sql;
import org.hibernate.query.QueryLogging;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class NativeQueryLogging {
public static final Logger LOGGER = QueryLogging.subLogger( "native" );
public static final boolean DEBUG_ENABLED = LOGGER.isDebugEnabled();
public static final boolean TRACE_ENABLED = LOGGER.isTraceEnabled();
}

View File

@ -19,6 +19,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import javax.persistence.AttributeConverter;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
@ -106,6 +108,7 @@ public class NativeQueryImpl<R>
private final QueryParameterBindings parameterBindings;
private final ResultSetMappingImpl resultSetMapping;
private final boolean resultMappingSuppliedToCtor;
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
@ -120,56 +123,78 @@ public class NativeQueryImpl<R>
public NativeQueryImpl(
NamedNativeQueryMemento memento,
SharedSessionContractImplementor session) {
super( session );
this(
memento,
() -> {
if ( memento.getResultMappingName() != null ) {
return new ResultSetMappingImpl( memento.getResultMappingName() );
}
else if ( memento.getResultMappingClass() != null ) {
return new ResultSetMappingImpl( memento.getResultMappingClass().getName() );
}
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( memento.getSqlString(), session );
return new ResultSetMappingImpl( memento.getSqlString() );
},
(resultSetMapping, querySpaceConsumer, context ) -> {
if ( memento.getResultMappingName() != null ) {
final NamedResultSetMappingMemento resultSetMappingMemento = session.getFactory()
.getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( memento.getResultMappingName() );
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
return true;
}
this.sqlString = parameterInterpretation.getAdjustedSqlString();
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
if ( memento.getResultMappingClass() != null ) {
resultSetMapping.addResultBuilder(
Builders.implicitEntityResultBuilder(
memento.getResultMappingClass(),
context
)
);
return true;
}
if ( memento.getResultMappingName() != null ) {
this.resultSetMapping = new ResultSetMappingImpl( memento.getResultMappingName() );
final NamedResultSetMappingMemento resultSetMappingMemento = getSessionFactory().getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( memento.getResultMappingName() );
resultSetMappingMemento.resolve(
resultSetMapping,
this::addSynchronizedQuerySpace,
this
);
}
else if ( memento.getResultMappingClass() != null ) {
this.resultSetMapping = new ResultSetMappingImpl( memento.getResultMappingName() );
resultSetMapping.addResultBuilder(
Builders.implicitEntityResultBuilder(
memento.getResultMappingClass(),
this
)
);
}
else {
this.resultSetMapping = new ResultSetMappingImpl( sqlString );
}
applyOptions( memento );
return false;
},
session
);
}
private NativeQueryImpl(
String resultMappingIdentifier,
@FunctionalInterface
private interface ResultSetMappingHandler {
boolean resolveResultSetMapping(
ResultSetMappingImpl resultSetMapping,
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context);
}
public NativeQueryImpl(
NamedNativeQueryMemento memento,
Supplier<ResultSetMappingImpl> resultSetMappingCreator,
ResultSetMappingHandler resultSetMappingHandler,
SharedSessionContractImplementor session) {
super( session );
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( memento.getSqlString(), session );
final String mementoSqlString = memento.getSqlString();
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( mementoSqlString, session );
this.sqlString = parameterInterpretation.getAdjustedSqlString();
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.querySpaces = new HashSet<>();
this.resultSetMapping = new ResultSetMappingImpl( resultMappingIdentifier );
this.resultSetMapping = resultSetMappingCreator.get();
//noinspection UnnecessaryLocalVariable
final boolean appliedAnyResults = resultSetMappingHandler.resolveResultSetMapping(
resultSetMapping,
querySpaces::add,
this
);
this.resultMappingSuppliedToCtor = appliedAnyResults;
applyOptions( memento );
}
@ -181,12 +206,25 @@ public class NativeQueryImpl<R>
NamedNativeQueryMemento memento,
Class<R> resultJavaType,
SharedSessionContractImplementor session) {
this( memento, session );
this(
memento,
() -> new ResultSetMappingImpl( resultJavaType.getName() ),
(resultSetMapping, querySpaceConsumer, context) -> {
if ( resultJavaType != null ) {
// todo (6.0) : need to add handling for `javax.persistence.NamedNativeQuery#resultSetMapping`
// and `javax.persistence.NamedNativeQuery#resultClass`
// todo (6.0) : really `resultJavaType` could be any type nature - basic, embedded, entity
// todo (6.0) : relatedly, does `resultJavaType` come from `NamedNativeQuery#resultClass`?
resultSetMapping.addResultBuilder(
Builders.implicitEntityResultBuilder( resultJavaType, context )
);
return true;
}
return false;
},
session
);
}
/**
@ -196,13 +234,21 @@ public class NativeQueryImpl<R>
NamedNativeQueryMemento memento,
String resultSetMappingName,
SharedSessionContractImplementor session) {
this( resultSetMappingName, memento, session );
this(
memento,
() -> new ResultSetMappingImpl( resultSetMappingName ),
(resultSetMapping, querySpaceConsumer, context) -> {
final NamedResultSetMappingMemento mappingMemento = session.getFactory()
.getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( resultSetMappingName );
assert mappingMemento != null;
mappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
return true;
},
session
);
session.getFactory()
.getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( resultSetMappingName )
.resolve( resultSetMapping, this::addSynchronizedQuerySpace, this );
}
public NativeQueryImpl(
@ -211,6 +257,13 @@ public class NativeQueryImpl<R>
AbstractSharedSessionContract session) {
super( session );
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sqlString, session );
this.sqlString = parameterInterpretation.getAdjustedSqlString();
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultSetMapping = new ResultSetMappingImpl( resultSetMappingMemento.getName() );
resultSetMappingMemento.resolve(
resultSetMapping,
@ -218,12 +271,7 @@ public class NativeQueryImpl<R>
this
);
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sqlString, session );
this.sqlString = parameterInterpretation.getAdjustedSqlString();
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultMappingSuppliedToCtor = true;
}
private ParameterInterpretation resolveParameterInterpretation(
@ -268,6 +316,7 @@ public class NativeQueryImpl<R>
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultSetMapping = new ResultSetMappingImpl( sqlString );
this.resultMappingSuppliedToCtor = false;
}
@Override
@ -310,20 +359,29 @@ public class NativeQueryImpl<R>
}
@Override
protected boolean canApplyAliasSpecificLockModes() {
return false;
public LockModeType getLockMode() {
throw new IllegalStateException( "Illegal attempt to get lock mode on a native-query" );
}
@Override
protected void verifySettingLockMode() {
throw new IllegalStateException( "Illegal attempt to set lock mode on a native query" );
public NativeQueryImplementor<R> setLockOptions(LockOptions lockOptions) {
super.setLockOptions( lockOptions );
return this;
}
@Override
protected void verifySettingAliasSpecificLockModes() {
throw new IllegalStateException( "Illegal attempt to set lock mode on a native query" );
public NativeQueryImplementor<R> setLockMode(String alias, LockMode lockMode) {
super.setLockMode( alias, lockMode );
return this;
}
@Override
public NativeQueryImplementor<R> setLockMode(LockModeType lockModeType) {
throw new IllegalStateException( "Illegal attempt to set lock mode on a native-query" );
}
@Override
public Query<R> applyGraph(RootGraph graph, GraphSemantic semantic) {
throw new HibernateException( "A native SQL query cannot use EntityGraphs" );
@ -331,14 +389,22 @@ public class NativeQueryImpl<R>
@Override
public NativeQueryImplementor<R> setTupleTransformer(TupleTransformer transformer) {
//noinspection unchecked
return (NativeQueryImplementor) super.setTupleTransformer( transformer );
return (NativeQueryImplementor<R>) super.setTupleTransformer( transformer );
}
@Override
public NativeQueryImplementor<R> setResultListTransformer(ResultListTransformer transformer) {
//noinspection unchecked
return (NativeQueryImplementor) super.setResultListTransformer( transformer );
return (NativeQueryImplementor<R>) super.setResultListTransformer( transformer );
}
protected Boolean isSelectQuery() {
if ( resultMappingSuppliedToCtor
|| resultSetMapping.getNumberOfResultBuilders() > 0
|| isReadOnly() ) {
return true;
}
return null;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -795,23 +861,6 @@ public class NativeQueryImpl<R>
return this;
}
@Override
public NativeQueryImplementor<R> setLockOptions(LockOptions lockOptions) {
super.setLockOptions( lockOptions );
return this;
}
@Override
public NativeQueryImplementor<R> setLockMode(String alias, LockMode lockMode) {
super.setLockMode( alias, lockMode );
return this;
}
@Override
public NativeQueryImplementor<R> setLockMode(LockModeType lockModeType) {
throw new IllegalStateException( "Illegal attempt to set lock mode on a native SQL query" );
}
@Override
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> javaType) {

View File

@ -14,6 +14,7 @@ import java.util.Map;
import org.hibernate.QueryException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.internal.QueryParameterNamedImpl;
import org.hibernate.query.internal.QueryParameterPositionalImpl;
import org.hibernate.query.spi.QueryParameterImplementor;

View File

@ -44,6 +44,16 @@ import org.hibernate.query.spi.QueryImplementor;
public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQuery<R>, NameableQuery {
NativeQueryImplementor setCollectionKey(Object key);
@Override
default LockOptions getLockOptions() {
return null;
}
@Override
default LockModeType getLockMode() {
return null;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// covariant overrides - NativeQuery

View File

@ -6,13 +6,15 @@
*/
package org.hibernate.query.sqm;
import org.hibernate.HibernateException;
/**
* Represents a general uncaught problem performing the interpretation. This might indicate
* a semantic (user sqm) problem or a bug in the parser.
*
* @author Steve Ebersole
*/
public class InterpretationException extends RuntimeException {
public class InterpretationException extends HibernateException {
public InterpretationException(String query) {
this( query, null );
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.query.sqm;
import org.hibernate.HibernateException;
import org.hibernate.query.SemanticException;
/**
@ -14,7 +15,7 @@ import org.hibernate.query.SemanticException;
*
* @author Steve Ebersole
*/
public class ParsingException extends RuntimeException {
public class ParsingException extends HibernateException {
public ParsingException(String message) {
super( message );
}

View File

@ -11,6 +11,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.LockModeType;
import javax.persistence.Parameter;
import javax.persistence.PersistenceException;
import javax.persistence.Tuple;
@ -39,6 +40,7 @@ import org.hibernate.query.spi.HqlInterpretation;
import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.NonSelectQueryPlan;
import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
@ -52,7 +54,6 @@ import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
@ -300,7 +301,7 @@ public class QuerySqmImpl<R>
return parameterBindings;
}
private boolean isSelect() {
protected Boolean isSelectQuery() {
return sqmStatement instanceof SqmSelectStatement;
}
@ -314,7 +315,7 @@ public class QuerySqmImpl<R>
}
@Override
public Query<R> applyGraph(RootGraph graph, GraphSemantic semantic) {
public HqlQueryImplementor<R> applyGraph(RootGraph graph, GraphSemantic semantic) {
queryOptions.applyGraph( (RootGraphImplementor<?>) graph, semantic );
return this;
}
@ -359,21 +360,23 @@ public class QuerySqmImpl<R>
}
@Override
protected boolean canApplyAliasSpecificLockModes() {
return isSelect();
}
@Override
protected void verifySettingLockMode() {
if ( !isSelect() ) {
throw new IllegalStateException( "Illegal attempt to set lock mode on a non-SELECT query" );
public LockModeType getLockMode() {
if ( ! isSelectQuery() ) {
throw new IllegalStateException( "Illegal attempt to access lock-mode for non-select query" );
}
return super.getLockMode();
}
@Override
protected void verifySettingAliasSpecificLockModes() {
// todo : add a specific Dialect check as well? - if not supported, maybe that can trigger follow-on locks?
verifySettingLockMode();
public HqlQueryImplementor<R> setLockMode(LockModeType lockModeType) {
if ( ! LockModeType.NONE.equals( lockModeType ) ) {
if ( ! isSelectQuery() ) {
throw new IllegalStateException( "Illegal attempt to access lock-mode for non-select query" );
}
}
return (HqlQueryImplementor<R>) super.setLockMode( lockModeType );
}
@Override

View File

@ -19,13 +19,14 @@ public class SqmCreationProcessingStateImpl implements SqmCreationProcessingStat
private final SqmCreationState creationState;
private final SqmQuery<?> processingQuery;
private final SqmPathRegistryImpl processingIndex = new SqmPathRegistryImpl( this );
private final SqmPathRegistryImpl processingIndex;
public SqmCreationProcessingStateImpl(
SqmQuery<?> processingQuery,
SqmCreationState creationState) {
this.processingQuery = processingQuery;
this.creationState = creationState;
this.processingIndex = new SqmPathRegistryImpl( this );
}
@Override

View File

@ -22,10 +22,12 @@ import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.dialect.function.TimestampaddFunction;
import org.hibernate.dialect.function.TimestampdiffFunction;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.internal.util.collections.StandardStack;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
@ -39,9 +41,9 @@ import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.BinaryArithmeticOperator;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.UnaryArithmeticOperator;
import org.hibernate.query.internal.QueryHelper;
import org.hibernate.query.spi.QueryOptions;
@ -59,6 +61,7 @@ import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.EntityValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.PluralValuedSimplePathInterpretation;
import org.hibernate.query.sqm.sql.internal.SqlAstProcessingStateImpl;
import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl;
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
@ -112,6 +115,7 @@ import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmEmptinessPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmExistsPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
@ -156,6 +160,7 @@ import org.hibernate.sql.ast.tree.expression.Every;
import org.hibernate.sql.ast.tree.expression.Expression;
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.QueryLiteral;
import org.hibernate.sql.ast.tree.expression.Star;
@ -186,11 +191,12 @@ import org.hibernate.sql.exec.spi.JdbcParameters;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger;
import static org.hibernate.internal.util.NullnessHelper.coalesce;
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
import static org.hibernate.query.BinaryArithmeticOperator.MULTIPLY;
import static org.hibernate.query.BinaryArithmeticOperator.SUBTRACT;
@ -217,6 +223,8 @@ public abstract class BaseSqmToSqlAstConverter
}
private final SqlAstCreationContext creationContext;
private final SessionFactoryImplementor sessionFactory;
private final QueryOptions queryOptions;
private final LoadQueryInfluencers loadQueryInfluencers;
@ -247,7 +255,10 @@ public abstract class BaseSqmToSqlAstConverter
DomainParameterXref domainParameterXref,
QueryParameterBindings domainParameterBindings) {
super( creationContext.getServiceRegistry() );
this.creationContext = creationContext;
this.sessionFactory = creationContext.getSessionFactory();
this.queryOptions = queryOptions;
this.loadQueryInfluencers = loadQueryInfluencers;
this.domainParameterXref = domainParameterXref;
@ -2288,6 +2299,68 @@ public abstract class BaseSqmToSqlAstConverter
return new ComparisonPredicate( lhs, predicate.getSqmOperator(), rhs );
}
@Override
public Object visitIsEmptyPredicate(SqmEmptinessPredicate predicate) {
final QuerySpec subQuerySpec = new QuerySpec( false, 1 );
final SqlAstProcessingState parentState = getProcessingStateStack().getCurrent();
final SqlAstProcessingStateImpl subQueryState = new SqlAstProcessingStateImpl(
parentState,
this,
currentClauseStack::getCurrent
);
getProcessingStateStack().push( subQueryState );
final SqmPluralValuedSimplePath<?> sqmPluralPath = predicate.getPluralPath();
final NavigablePath pluralPathNavPath = sqmPluralPath.getNavigablePath();
final NavigablePath parentNavPath = pluralPathNavPath.getParent();
assert parentNavPath != null;
final TableGroup parentTableGroup = parentState
.getSqlAstCreationState()
.getFromClauseAccess()
.getTableGroup( parentNavPath );
subQueryState.getSqlAstCreationState().getFromClauseAccess().registerTableGroup( parentNavPath, parentTableGroup );
final SqmPathInterpretation<?> sqmPathInterpretation = visitPluralValuedPath( sqmPluralPath );
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) sqmPathInterpretation.getExpressionType();
// note : do not add to `parentTableGroup` as a join
final TableGroupJoin tableGroupJoin = pluralAttributeMapping.createTableGroupJoin(
pluralPathNavPath,
parentTableGroup,
sqmPluralPath.getExplicitAlias(),
SqlAstJoinType.LEFT,
LockMode.NONE,
sqlAliasBaseManager,
subQueryState,
creationContext
);
final TableGroup collectionTableGroup = tableGroupJoin.getJoinedGroup();
subQuerySpec.getFromClause().addRoot( collectionTableGroup );
subQuerySpec.applyPredicate( tableGroupJoin.getPredicate() );
final ForeignKeyDescriptor collectionKeyDescriptor = pluralAttributeMapping.getKeyDescriptor();
final int jdbcTypeCount = collectionKeyDescriptor.getJdbcTypeCount( sessionFactory.getTypeConfiguration() );
assert jdbcTypeCount > 0;
final JdbcLiteral<Integer> jdbcLiteral = new JdbcLiteral<>( 1, StandardBasicTypes.INTEGER );
subQuerySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl(1,0, jdbcLiteral )
);
return new ExistsPredicate( subQuerySpec );
}
@Override
public BetweenPredicate visitBetweenPredicate(SqmBetweenPredicate predicate) {
final Expression expression;

View File

@ -18,6 +18,7 @@ import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SingularAttribute;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
@ -154,7 +155,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
@SuppressWarnings("unchecked")
public SqmExpression<Class<? extends T>> type() {
if ( pathTypeExpression == null ) {
final String discriminatorPathName = "{type}";
final String discriminatorPathName = EntityDiscriminatorMapping.ROLE_NAME;
final NavigablePath discriminatorNavigablePath = getNavigablePath().append( discriminatorPathName );
final DomainType sqmNodeType = getReferencedPathSource().getSqmPathType();

View File

@ -8,23 +8,23 @@ package org.hibernate.query.sqm.tree.predicate;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
/**
* @author Steve Ebersole
*/
public class SqmEmptinessPredicate extends AbstractNegatableSqmPredicate {
private final SqmPath<?> pluralPath;
private final SqmPluralValuedSimplePath<?> pluralPath;
public SqmEmptinessPredicate(
SqmPath pluralPath,
SqmPluralValuedSimplePath pluralPath,
boolean negated,
NodeBuilder nodeBuilder) {
super( negated, nodeBuilder );
this.pluralPath = pluralPath;
}
public SqmPath<?> getPluralPath() {
public SqmPluralValuedSimplePath<?> getPluralPath() {
return pluralPath;
}

View File

@ -0,0 +1,16 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.ast.spi;
import org.hibernate.sql.ast.tree.expression.Expression;
/**
* @author Steve Ebersole
*/
public interface SqlExpressionAccess {
Expression getSqlExpression();
}

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.results.internal;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlExpressionAccess;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.descriptor.ValueExtractor;
@ -34,7 +35,7 @@ import java.util.Objects;
*
* @author Steve Ebersole
*/
public class SqlSelectionImpl implements SqlSelection {
public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
private final int jdbcPosition;
private final int valuesArrayPosition;
private final Expression sqlExpression;
@ -94,4 +95,9 @@ public class SqlSelectionImpl implements SqlSelection {
public int hashCode() {
return Objects.hash( jdbcPosition, valuesArrayPosition, sqlExpression );
}
@Override
public Expression getSqlExpression() {
return sqlExpression;
}
}

View File

@ -20,7 +20,7 @@ import org.hibernate.jpa.test.metamodel.Order_;
import org.junit.Test;
/**
* Similar to {@link org.hibernate.test.jpa.ql.OnKeywordTest}, but here testing from JPA criteria queries.
* Similar to {@link org.hibernate.orm.test.query.hql.OnKeywordTest}, but here testing from JPA criteria queries.
*
* @author Steve Ebersole
*/

View File

@ -13,6 +13,7 @@ import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.JpaComplianceStub;
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl;
@ -60,7 +61,7 @@ public class HqlTranslationNoFactoryTests {
final MetadataImplementor bootModel = modelScope.getDomainModel();
final TypeConfiguration typeConfiguration = bootModel.getTypeConfiguration();
final JpaMetamodelImpl jpaMetamodel = new JpaMetamodelImpl( typeConfiguration );
final JpaMetamodelImpl jpaMetamodel = new JpaMetamodelImpl( typeConfiguration, new JpaComplianceStub() );
// todo (6.0) (quarkus) : we should limit the type of the last argument here from `RuntimeModelCreationContext`
// which assumes access to SessionFactory

View File

@ -9,4 +9,4 @@
* Test package for investigating JPA TCK failures - to reproduce them
* and, if caused by a Hibernate bug, make sure it does not regress later
*/
package org.hibernate.test.jpa.compliance;
package org.hibernate.orm.test.jpa.compliance;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import java.util.Collections;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.RollbackException;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Entity;
import javax.persistence.Id;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Parameter;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.LockModeType;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import java.util.Date;
import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import java.util.ArrayList;
import java.util.List;
@ -39,7 +39,9 @@ public class QueryExecutionTest extends BaseNonConfigCoreFunctionalTestCase {
inTransaction(
session -> {
final List nonDistinctResult = session.createQuery( "select c from Customer c join fetch c.orders" ).list();
assertThat( nonDistinctResult.size(), CoreMatchers.is( 2 ) );
// note: this was historically `2` because Hibernate would return a root result for each of its fetched rows.
// - that was confusing behavior for users. we have changed this in 6 to be more logical
assertThat( nonDistinctResult.size(), CoreMatchers.is( 1 ) );
final List distinctResult = session.createQuery( "select distinct c from Customer c join fetch c.orders" ).list();
assertThat( distinctResult.size(), CoreMatchers.is( 1 ) );

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import java.util.Date;
import javax.persistence.Entity;
@ -20,6 +20,7 @@ import org.hibernate.dialect.H2Dialect;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.QueryParameter;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.hibernate.test.sql.storedproc.StoredProcedureResultSetMappingTest;
@ -31,6 +32,7 @@ import static org.junit.Assert.fail;
* @author Steve Ebersole
*/
@RequiresDialect( H2Dialect.class )
@FailureExpected( message = "Procedure/function support not yet implemented", jiraKey = "n/a" )
public class StoredProcedureApiTests extends BaseNonConfigCoreFunctionalTestCase {

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.caching;
package org.hibernate.orm.test.jpa.compliance.tck2_2.caching;
import java.util.HashMap;
import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.caching;
package org.hibernate.orm.test.jpa.compliance.tck2_2.caching;
import java.util.Map;
import javax.persistence.Cacheable;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.caching;
package org.hibernate.orm.test.jpa.compliance.tck2_2.caching;
import java.util.Map;
import javax.persistence.Cacheable;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.joincolumn;
package org.hibernate.orm.test.jpa.compliance.tck2_2.joincolumn;
import java.util.Collections;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.joincolumn;
package org.hibernate.orm.test.jpa.compliance.tck2_2.joincolumn;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.joincolumn;
package org.hibernate.orm.test.jpa.compliance.tck2_2.joincolumn;
import javax.persistence.CascadeType;
import javax.persistence.Entity;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn;
package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap;
import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn;
package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap;
import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn;
package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap;
import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn;
package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap;
import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn;
package org.hibernate.orm.test.jpa.compliance.tck2_2.mapkeycolumn;
import java.util.HashMap;
import java.util.Map;

View File

@ -10,4 +10,4 @@
*
* @see org.hibernate.test.jpa.compliance
*/
package org.hibernate.test.jpa.compliance.tck2_2;
package org.hibernate.orm.test.jpa.compliance.tck2_2;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.ql;
package org.hibernate.orm.test.query.hql;
import org.hibernate.Session;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.jpa.ql;
package org.hibernate.orm.test.query.hql;
import java.math.BigDecimal;

View File

@ -10,10 +10,17 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit;
import javax.persistence.TemporalType;
import org.hibernate.boot.Metadata;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.testing.orm.domain.StandardDomainModel;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
@ -35,6 +42,13 @@ public class NativeQueryParameterTests {
);
}
@Test
public void testJpaStylePositionalParametersInNativeSql(SessionFactoryScope scope) {
scope.inTransaction(
s -> s.createNativeQuery( "select t.subject from ticket t where t.key = ?1" ).setParameter( 1, "ABC-123" ).list()
);
}
@Test
public void testTypedParameterBinding(SessionFactoryScope scope) {
scope.inTransaction(

View File

@ -45,9 +45,9 @@ public class JPAQLComplianceTest extends AbstractJPATest {
Session s = openSession( );
// a control test (a user reported that the JPA 'case insensitivity' support
// caused problems with the "discriminator resolution" code; unable to reproduce)...
s.createQuery( "from MyEntity e where e.class = MySubclassEntity" );
s.createQuery( "from MyEntity e where e.other.class = MySubclassEntity" );
s.createQuery( "from MyEntity where other.class = MySubclassEntity" );
s.createQuery( "select E from MyEntity e where other.class = MySubclassEntity" );
s.createQuery( "select e from MyEntity e where e.other.class = MySubclassEntity" );
s.createQuery( "select e from MyEntity E where e.class = MySubclassEntity" );
s.createQuery( "select object(I) from Item i").list();
s.close();

View File

@ -1,22 +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.test.jpa.ql;
import org.hibernate.test.jpa.AbstractJPATest;
import org.junit.Test;
/**
* @author Steve Ebersole
*/
public class NativeQueryTest extends AbstractJPATest {
@Test
public void testJpaStylePositionalParametersInNativeSql() {
inTransaction(
s -> s.createNativeQuery( "select NAME from EJB3_ITEM where ITEM_ID = ?1" ).setParameter( 1, 123L ).list()
);
}
}

View File

@ -12,7 +12,7 @@ log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.appender.stdout2=org.apache.log4j.ConsoleAppender
log4j.appender.stdout2.Target=System.out
log4j.appender.stdout2.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout2.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{5}:%L - %m%n
log4j.appender.stdout2.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{5}:(%C{1}:%L) - %m%n
log4j.appender.unclosedSessionFactoryFile=org.apache.log4j.FileAppender
log4j.appender.unclosedSessionFactoryFile.append=true
@ -29,7 +29,7 @@ log4j.logger.org.hibernate.orm.sql.results=debug
log4j.logger.org.hibernate.orm.graph=debug
log4j.logger.org.hibernate.orm.query.sqm=debug
log4j.logger.org.hibernate.orm.query.hql=debug
log4j.logger.org.hibernate.orm.query.hql=trace
log4j.logger.org.hibernate.sql.results.graph.DomainResultGraphPrinter=debug
log4j.logger.org.hibernate.tool.hbm2ddl=trace