further work on query parser exceptions
I missed a couple of things
This commit is contained in:
parent
d859f43748
commit
9adffa4e4f
|
@ -7,8 +7,22 @@
|
||||||
package org.hibernate;
|
package org.hibernate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A problem occurred translating a Hibernate query to SQL
|
* A problem occurred translating a Hibernate query to SQL due to illegal query
|
||||||
* due to invalid query syntax, or some similar problem.
|
* syntax, an operation which is not well-typed, an unresolvable reference to
|
||||||
|
* an entity or attribute, an unknown named query, or any similar problem. This
|
||||||
|
* exception type is not used to represent failures that occur while executing
|
||||||
|
* a query or reading the result set of a query.
|
||||||
|
* <p>
|
||||||
|
* The two most important subtypes are:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link org.hibernate.query.SyntaxException}, which represents a syntax
|
||||||
|
* error in the HQL query, and
|
||||||
|
* <li>{@link org.hibernate.query.SemanticException}, which represents an error
|
||||||
|
* in the semantics of the query.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @see org.hibernate.query.SemanticException
|
||||||
|
* @see org.hibernate.query.SyntaxException
|
||||||
*/
|
*/
|
||||||
public class QueryException extends HibernateException {
|
public class QueryException extends HibernateException {
|
||||||
private final String queryString;
|
private final String queryString;
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.metamodel.model.domain.internal;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.query.TerminalPathException;
|
import org.hibernate.query.sqm.TerminalPathException;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
|
|
@ -47,7 +47,7 @@ import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
import org.hibernate.query.EntityReferenceException;
|
import org.hibernate.query.sqm.EntityTypeException;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||||
|
@ -164,7 +164,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
public <X> EntityDomainType<X> resolveHqlEntityReference(String entityName) {
|
public <X> EntityDomainType<X> resolveHqlEntityReference(String entityName) {
|
||||||
final EntityDomainType<X> hqlEntityReference = getHqlEntityReference( entityName );
|
final EntityDomainType<X> hqlEntityReference = getHqlEntityReference( entityName );
|
||||||
if ( hqlEntityReference == null ) {
|
if ( hqlEntityReference == null ) {
|
||||||
throw new EntityReferenceException( "Could not resolve entity reference: " + entityName );
|
throw new EntityTypeException( "Could not resolve entity name '" + entityName + "'", entityName );
|
||||||
}
|
}
|
||||||
return hqlEntityReference;
|
return hqlEntityReference;
|
||||||
}
|
}
|
||||||
|
@ -444,7 +444,8 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
|
|
||||||
// otherwise, try to handle it as a polymorphic reference
|
// otherwise, try to handle it as a polymorphic reference
|
||||||
{
|
{
|
||||||
final EntityDomainType<T> polymorphicDomainType = (EntityDomainType<T>) polymorphicEntityReferenceMap.get( javaType );
|
final EntityDomainType<T> polymorphicDomainType =
|
||||||
|
(EntityDomainType<T>) polymorphicEntityReferenceMap.get( javaType );
|
||||||
if ( polymorphicDomainType != null ) {
|
if ( polymorphicDomainType != null ) {
|
||||||
return polymorphicDomainType;
|
return polymorphicDomainType;
|
||||||
}
|
}
|
||||||
|
@ -495,7 +496,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new EntityReferenceException( "Could not resolve entity reference : " + javaType.getName() );
|
throw new EntityTypeException( "Could not resolve entity class '" + javaType.getName() + "'", javaType.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
|
||||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*/
|
|
||||||
package org.hibernate.query;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that a reference to an entity did not resolve to
|
|
||||||
* a mapped entity class.
|
|
||||||
*
|
|
||||||
* @apiNote extends {@link IllegalArgumentException} to
|
|
||||||
* satisfy a questionable requirement of the JPA criteria
|
|
||||||
* query API
|
|
||||||
*
|
|
||||||
* @since 6.3
|
|
||||||
*
|
|
||||||
* @author Gavin King
|
|
||||||
*/
|
|
||||||
public class EntityReferenceException extends IllegalArgumentException {
|
|
||||||
public EntityReferenceException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,7 +13,10 @@ import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that validation and translation of one or more named
|
* Indicates that validation and translation of one or more named
|
||||||
* queries failed at initialization time.
|
* queries failed at initialization time. This exception packages
|
||||||
|
* every {@link org.hibernate.QueryException} that occurred for an
|
||||||
|
* invalid HQL/JPQL query, together with any exceptions that indicate
|
||||||
|
* problems with named native SQL queries.
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,23 +7,22 @@
|
||||||
package org.hibernate.query;
|
package org.hibernate.query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates an attempt to use a path in an unsupported way
|
* Indicates a problem with a path expression in HQL/JPQL.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*
|
*
|
||||||
* @see PathElementException
|
* @see org.hibernate.query.sqm.UnknownPathException
|
||||||
* @see TerminalPathException
|
|
||||||
*/
|
*/
|
||||||
public class PathException extends SemanticException {
|
public class PathException extends SemanticException {
|
||||||
public PathException(String message) {
|
public PathException(String message) {
|
||||||
super( message );
|
super( message );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated This is currently unused
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true, since = "6.3")
|
|
||||||
public PathException(String message, Exception cause) {
|
public PathException(String message, Exception cause) {
|
||||||
super( message, cause );
|
super( message, cause );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PathException(String message, String hql, Exception cause) {
|
||||||
|
super(message, hql, cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ package org.hibernate.query;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates a mismatch between a Query's expected and actual result types
|
* Indicates a mismatch between the expected and actual result types of a query.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,10 +9,12 @@ package org.hibernate.query;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates a request for a named-query when no query is
|
* Occurs when a named query is requested, and there is no known
|
||||||
* registered under that name
|
* HQL or native SQL query registered under the given name.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
*
|
||||||
|
* @see org.hibernate.query.named.NamedObjectRepository
|
||||||
*/
|
*/
|
||||||
public class UnknownNamedQueryException extends QueryException {
|
public class UnknownNamedQueryException extends QueryException {
|
||||||
public UnknownNamedQueryException(String queryName) {
|
public UnknownNamedQueryException(String queryName) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ import org.hibernate.query.ParameterLabelException;
|
||||||
import org.hibernate.query.PathException;
|
import org.hibernate.query.PathException;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.SemanticException;
|
||||||
import org.hibernate.query.TerminalPathException;
|
import org.hibernate.query.sqm.TerminalPathException;
|
||||||
import org.hibernate.query.criteria.JpaCteCriteria;
|
import org.hibernate.query.criteria.JpaCteCriteria;
|
||||||
import org.hibernate.query.criteria.JpaCteCriteriaAttribute;
|
import org.hibernate.query.criteria.JpaCteCriteriaAttribute;
|
||||||
import org.hibernate.query.criteria.JpaCteCriteriaType;
|
import org.hibernate.query.criteria.JpaCteCriteriaType;
|
||||||
|
|
|
@ -14,15 +14,17 @@ import org.antlr.v4.runtime.NoViableAltException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.grammars.hql.HqlLexer;
|
import org.hibernate.grammars.hql.HqlLexer;
|
||||||
import org.hibernate.grammars.hql.HqlParser;
|
import org.hibernate.grammars.hql.HqlParser;
|
||||||
import org.hibernate.query.EntityReferenceException;
|
import org.hibernate.query.sqm.EntityTypeException;
|
||||||
import org.hibernate.query.PathElementException;
|
import org.hibernate.query.sqm.PathElementException;
|
||||||
import org.hibernate.query.SyntaxException;
|
import org.hibernate.query.SyntaxException;
|
||||||
import org.hibernate.query.TerminalPathException;
|
import org.hibernate.query.sqm.TerminalPathException;
|
||||||
import org.hibernate.query.hql.HqlLogging;
|
import org.hibernate.query.hql.HqlLogging;
|
||||||
import org.hibernate.query.hql.HqlTranslator;
|
import org.hibernate.query.hql.HqlTranslator;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationOptions;
|
import org.hibernate.query.hql.spi.SqmCreationOptions;
|
||||||
import org.hibernate.query.sqm.InterpretationException;
|
import org.hibernate.query.sqm.InterpretationException;
|
||||||
import org.hibernate.query.sqm.ParsingException;
|
import org.hibernate.query.sqm.ParsingException;
|
||||||
|
import org.hibernate.query.sqm.UnknownEntityException;
|
||||||
|
import org.hibernate.query.sqm.UnknownPathException;
|
||||||
import org.hibernate.query.sqm.internal.SqmTreePrinter;
|
import org.hibernate.query.sqm.internal.SqmTreePrinter;
|
||||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
@ -78,9 +80,15 @@ public class StandardHqlTranslator implements HqlTranslator {
|
||||||
|
|
||||||
return sqmStatement;
|
return sqmStatement;
|
||||||
}
|
}
|
||||||
catch (QueryException | PathElementException | TerminalPathException | EntityReferenceException e) {
|
catch (QueryException e) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
catch (PathElementException | TerminalPathException e) {
|
||||||
|
throw new UnknownPathException( e.getMessage(), query, e );
|
||||||
|
}
|
||||||
|
catch (EntityTypeException e) {
|
||||||
|
throw new UnknownEntityException( e.getMessage(), e.getReference(), e );
|
||||||
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
// this is some sort of "unexpected" exception, i.e. something buglike
|
// this is some sort of "unexpected" exception, i.e. something buglike
|
||||||
throw new InterpretationException( query, e );
|
throw new InterpretationException( query, e );
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.boot.Metadata;
|
import org.hibernate.boot.Metadata;
|
||||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||||
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
||||||
|
@ -18,16 +19,18 @@ import org.hibernate.boot.query.NamedProcedureCallDefinition;
|
||||||
import org.hibernate.boot.spi.MetadataImplementor;
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||||
import org.hibernate.query.EntityReferenceException;
|
import org.hibernate.query.sqm.EntityTypeException;
|
||||||
import org.hibernate.query.NamedQueryValidationException;
|
import org.hibernate.query.NamedQueryValidationException;
|
||||||
import org.hibernate.query.PathElementException;
|
import org.hibernate.query.sqm.PathElementException;
|
||||||
import org.hibernate.query.TerminalPathException;
|
import org.hibernate.query.sqm.TerminalPathException;
|
||||||
import org.hibernate.query.named.NamedObjectRepository;
|
import org.hibernate.query.named.NamedObjectRepository;
|
||||||
import org.hibernate.query.named.NamedQueryMemento;
|
import org.hibernate.query.named.NamedQueryMemento;
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.query.spi.QueryInterpretationCache;
|
import org.hibernate.query.spi.QueryInterpretationCache;
|
||||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||||
|
import org.hibernate.query.sqm.UnknownEntityException;
|
||||||
|
import org.hibernate.query.sqm.UnknownPathException;
|
||||||
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
|
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
@ -239,21 +242,24 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
|
||||||
// Check named HQL queries
|
// Check named HQL queries
|
||||||
log.debugf( "Checking %s named HQL queries", sqmMementoMap.size() );
|
log.debugf( "Checking %s named HQL queries", sqmMementoMap.size() );
|
||||||
for ( NamedSqmQueryMemento hqlMemento : sqmMementoMap.values() ) {
|
for ( NamedSqmQueryMemento hqlMemento : sqmMementoMap.values() ) {
|
||||||
|
final String queryString = hqlMemento.getHqlString();
|
||||||
|
final String registrationName = hqlMemento.getRegistrationName();
|
||||||
try {
|
try {
|
||||||
log.debugf( "Checking named HQL query: %s", hqlMemento.getRegistrationName() );
|
log.debugf( "Checking named HQL query: %s", registrationName );
|
||||||
String queryString = hqlMemento.getHqlString();
|
|
||||||
interpretationCache.resolveHqlInterpretation(
|
interpretationCache.resolveHqlInterpretation(
|
||||||
queryString,
|
queryString,
|
||||||
null,
|
null,
|
||||||
s -> queryEngine.getHqlTranslator().translate( queryString, null )
|
s -> queryEngine.getHqlTranslator().translate( queryString, null )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch ( HibernateException e ) {
|
catch ( QueryException e ) {
|
||||||
errors.put( hqlMemento.getRegistrationName(), e );
|
errors.put( registrationName, e );
|
||||||
}
|
}
|
||||||
catch ( PathElementException | TerminalPathException | EntityReferenceException e ) {
|
catch ( PathElementException | TerminalPathException e ) {
|
||||||
// JPA does not let these be HibernateExceptions in general
|
errors.put( registrationName, new UnknownPathException( e.getMessage(), queryString, e ) );
|
||||||
errors.put( hqlMemento.getRegistrationName(), new HibernateException(e) );
|
}
|
||||||
|
catch ( EntityTypeException e ) {
|
||||||
|
errors.put( registrationName, new UnknownEntityException( e.getMessage(), e.getReference(), e ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.query.sqm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that a reference to an entity, that is, a given entity name
|
||||||
|
* or Java class object, did not resolve to a known mapped entity type.
|
||||||
|
*
|
||||||
|
* @apiNote extends {@link IllegalArgumentException} to
|
||||||
|
* satisfy a questionable requirement of the JPA
|
||||||
|
* criteria query API
|
||||||
|
*
|
||||||
|
* @since 6.3
|
||||||
|
*
|
||||||
|
* @author Gavin King
|
||||||
|
*/
|
||||||
|
public class EntityTypeException extends IllegalArgumentException {
|
||||||
|
private final String reference;
|
||||||
|
|
||||||
|
public EntityTypeException(String message, String reference) {
|
||||||
|
super(message);
|
||||||
|
this.reference = reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity name or the name of the Java class.
|
||||||
|
*/
|
||||||
|
public String getReference() {
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,15 +4,15 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query;
|
package org.hibernate.query.sqm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that an element of a path did not resolve to
|
* Indicates that an element of a path did not resolve to
|
||||||
* a mapped program element.
|
* a mapped program element.
|
||||||
*
|
*
|
||||||
* @apiNote extends {@link IllegalArgumentException} to
|
* @apiNote extends {@link IllegalArgumentException} to
|
||||||
* satisfy a questionable requirement of the JPA criteria
|
* satisfy a questionable requirement of the JPA
|
||||||
* query API
|
* criteria query API
|
||||||
*
|
*
|
||||||
* @since 6.3
|
* @since 6.3
|
||||||
*
|
*
|
|
@ -11,7 +11,6 @@ import java.util.Locale;
|
||||||
import jakarta.persistence.metamodel.Bindable;
|
import jakarta.persistence.metamodel.Bindable;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.query.PathElementException;
|
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.query.sqm.tree.SqmExpressibleAccessor;
|
import org.hibernate.query.sqm.tree.SqmExpressibleAccessor;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
|
|
@ -4,15 +4,15 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query;
|
package org.hibernate.query.sqm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates an attempt to dereference a terminal path
|
* Indicates an attempt to dereference a terminal path
|
||||||
* (usually a path referring to something of basic type)
|
* (usually a path referring to something of basic type)
|
||||||
*
|
*
|
||||||
* @apiNote extends {@link IllegalStateException} to
|
* @apiNote extends {@link IllegalStateException} to
|
||||||
* satisfy a questionable requirement of the JPA criteria
|
* satisfy a questionable requirement of the JPA
|
||||||
* query API
|
* criteria query API
|
||||||
*
|
*
|
||||||
* @since 6.3
|
* @since 6.3
|
||||||
*
|
*
|
|
@ -9,14 +9,18 @@ package org.hibernate.query.sqm;
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.SemanticException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates we were not able to resolve a given "path structure" as an entity name.
|
* Indicates a failure to resolve an entity name in HQL to a known mapped
|
||||||
|
* entity type.
|
||||||
*
|
*
|
||||||
* @apiNote JPA generally requires this to be reported as the much less useful
|
* @apiNote The JPA criteria API requires that this problem be reported
|
||||||
* {@link IllegalArgumentException}.
|
* as an {@link IllegalArgumentException}, and so we usually
|
||||||
*
|
* throw {@link EntityTypeException} from the SQM objects, and
|
||||||
* todo (6.0) : account for this in the "exception conversion" handling
|
* then wrap as an instance of this exception type in the
|
||||||
|
* {@link org.hibernate.query.hql.HqlTranslator}.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
*
|
||||||
|
* @see EntityTypeException
|
||||||
*/
|
*/
|
||||||
public class UnknownEntityException extends SemanticException {
|
public class UnknownEntityException extends SemanticException {
|
||||||
private final String entityName;
|
private final String entityName;
|
||||||
|
@ -30,6 +34,11 @@ public class UnknownEntityException extends SemanticException {
|
||||||
this.entityName = entityName;
|
this.entityName = entityName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UnknownEntityException(String message, String entityName, Exception cause) {
|
||||||
|
super( message, cause );
|
||||||
|
this.entityName = entityName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getEntityName() {
|
public String getEntityName() {
|
||||||
return entityName;
|
return entityName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,30 +8,44 @@ package org.hibernate.query.sqm;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.PathException;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Indicates a failure to resolve an element of a path expression in HQL/JPQL.
|
||||||
*
|
*
|
||||||
*
|
* @apiNote The JPA criteria API requires that this sort of problem be reported
|
||||||
* todo (6.0) : account for this in the "exception conversion" handling
|
* as an {@link IllegalArgumentException} or {@link IllegalStateException},
|
||||||
|
* and so we usually throw {@link PathElementException} or
|
||||||
|
* {@link TerminalPathException} from the SQM objects, and then wrap
|
||||||
|
* as an instance of this exception type in the
|
||||||
|
* {@link org.hibernate.query.hql.HqlTranslator}.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
*
|
||||||
|
* @see PathElementException
|
||||||
|
* @see TerminalPathException
|
||||||
*/
|
*/
|
||||||
public class UnknownPathException extends SemanticException {
|
public class UnknownPathException extends PathException {
|
||||||
|
|
||||||
|
public UnknownPathException(String message) {
|
||||||
|
super( message );
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnknownPathException(String message, String hql, Exception cause) {
|
||||||
|
super( message, hql, cause );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static UnknownPathException unknownSubPath(SqmPath base, String name) {
|
public static UnknownPathException unknownSubPath(SqmPath base, String name) {
|
||||||
return new UnknownPathException(
|
return new UnknownPathException(
|
||||||
String.format(
|
String.format(
|
||||||
Locale.ROOT,
|
Locale.ROOT,
|
||||||
"Could not resolve path `%s` relative to %s (%s)",
|
"Could not resolve path element '%s' relative to '%s' (%s)",
|
||||||
name,
|
name,
|
||||||
base.getReferencedPathSource().getSqmPathType().getTypeName(),
|
base.getReferencedPathSource().getSqmPathType().getTypeName(),
|
||||||
base.getNavigablePath()
|
base.getNavigablePath()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UnknownPathException(String message) {
|
|
||||||
super( message );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.query.PathException;
|
import org.hibernate.query.PathException;
|
||||||
|
import org.hibernate.query.sqm.UnknownPathException;
|
||||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||||
|
@ -121,7 +122,7 @@ public class BasicValuedPathInterpretation<T> extends AbstractSqmPathInterpretat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new PathException( "Path '" + sqmPath.getNavigablePath() + "' did not reference a known model part" );
|
throw new UnknownPathException( "Path '" + sqmPath.getNavigablePath() + "' did not reference a known model part" );
|
||||||
}
|
}
|
||||||
|
|
||||||
final TableReference tableReference = tableGroup.resolveTableReference(
|
final TableReference tableReference = tableGroup.resolveTableReference(
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.query.sqm.tree.domain;
|
package org.hibernate.query.sqm.tree.domain;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.query.sqm.UnknownPathException;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.query.PathException;
|
import org.hibernate.query.PathException;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
|
@ -70,7 +71,7 @@ public class SqmBasicValuedSimplePath<T>
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
throw new PathException(
|
throw new UnknownPathException(
|
||||||
String.format(
|
String.format(
|
||||||
"Could not interpret attribute '%s' of basic-valued path '%s'",
|
"Could not interpret attribute '%s' of basic-valued path '%s'",
|
||||||
name, getNavigablePath()
|
name, getNavigablePath()
|
||||||
|
|
|
@ -16,7 +16,7 @@ import jakarta.persistence.metamodel.PluralAttribute;
|
||||||
import jakarta.persistence.metamodel.SingularAttribute;
|
import jakarta.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.query.PathException;
|
import org.hibernate.query.SemanticException;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.query.criteria.JpaPath;
|
import org.hibernate.query.criteria.JpaPath;
|
||||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||||
|
@ -138,7 +138,7 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
|
||||||
SqmExpression<?> selector,
|
SqmExpression<?> selector,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
throw new PathException( "Index operator applied to non-plural path '" + getNavigablePath() + "'" );
|
throw new SemanticException( "Index operator applied to non-plural path '" + getNavigablePath() + "'" );
|
||||||
}
|
}
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Covariant overrides
|
// Covariant overrides
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
// this is a reference to a collection outside the from-clause...
|
// this is a reference to a collection outside the from clause
|
||||||
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name );
|
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name );
|
||||||
if ( nature == null ) {
|
if ( nature == null ) {
|
||||||
throw new PathException( "Plural path '" + getNavigablePath()
|
throw new PathException( "Plural path '" + getNavigablePath()
|
||||||
|
|
|
@ -10,12 +10,12 @@ import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.query.PathException;
|
|
||||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.SqmExpressible;
|
import org.hibernate.query.sqm.SqmExpressible;
|
||||||
|
import org.hibernate.query.sqm.UnknownPathException;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||||
|
@ -85,7 +85,7 @@ public class SqmEnumLiteral<E extends Enum<E>> extends AbstractSqmExpression<E>
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
throw new PathException(
|
throw new UnknownPathException(
|
||||||
String.format(
|
String.format(
|
||||||
Locale.ROOT,
|
Locale.ROOT,
|
||||||
"Static enum reference [%s#%s] cannot be de-referenced",
|
"Static enum reference [%s#%s] cannot be de-referenced",
|
||||||
|
@ -100,7 +100,7 @@ public class SqmEnumLiteral<E extends Enum<E>> extends AbstractSqmExpression<E>
|
||||||
SqmExpression<?> selector,
|
SqmExpression<?> selector,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
throw new PathException(
|
throw new UnknownPathException(
|
||||||
String.format(
|
String.format(
|
||||||
Locale.ROOT,
|
Locale.ROOT,
|
||||||
"Static enum reference [%s#%s] cannot be de-referenced",
|
"Static enum reference [%s#%s] cannot be de-referenced",
|
||||||
|
|
|
@ -14,14 +14,13 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.query.PathException;
|
|
||||||
import org.hibernate.query.SemanticException;
|
|
||||||
import org.hibernate.query.criteria.JpaSelection;
|
import org.hibernate.query.criteria.JpaSelection;
|
||||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.SqmExpressible;
|
import org.hibernate.query.sqm.SqmExpressible;
|
||||||
|
import org.hibernate.query.sqm.UnknownPathException;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||||
|
@ -229,7 +228,7 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
throw new PathException(
|
throw new UnknownPathException(
|
||||||
String.format(
|
String.format(
|
||||||
Locale.ROOT,
|
Locale.ROOT,
|
||||||
"Static field reference [%s#%s] cannot be de-referenced",
|
"Static field reference [%s#%s] cannot be de-referenced",
|
||||||
|
@ -244,7 +243,7 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
|
||||||
SqmExpression<?> selector,
|
SqmExpression<?> selector,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
throw new PathException(
|
throw new UnknownPathException(
|
||||||
String.format(
|
String.format(
|
||||||
Locale.ROOT,
|
Locale.ROOT,
|
||||||
"Static field reference [%s#%s] cannot be de-referenced",
|
"Static field reference [%s#%s] cannot be de-referenced",
|
||||||
|
|
|
@ -6,13 +6,16 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.hql;
|
package org.hibernate.orm.test.hql;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.ScrollMode;
|
import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.ScrollableResults;
|
import org.hibernate.ScrollableResults;
|
||||||
import org.hibernate.dialect.AbstractHANADialect;
|
import org.hibernate.dialect.AbstractHANADialect;
|
||||||
|
import org.hibernate.dialect.DB2Dialect;
|
||||||
|
import org.hibernate.dialect.DerbyDialect;
|
||||||
import org.hibernate.dialect.SybaseASEDialect;
|
import org.hibernate.dialect.SybaseASEDialect;
|
||||||
|
|
||||||
import org.hibernate.query.PathElementException;
|
import org.hibernate.query.SemanticException;
|
||||||
|
import org.hibernate.query.sqm.UnknownPathException;
|
||||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||||
|
@ -43,22 +46,51 @@ import static org.junit.jupiter.api.Assertions.fail;
|
||||||
public class ScrollableCollectionFetchingTest {
|
public class ScrollableCollectionFetchingTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTupleReturnFails(SessionFactoryScope scope) {
|
@SkipForDialect(dialectClass=DB2Dialect.class, matchSubTypes = true)
|
||||||
|
@SkipForDialect(dialectClass= DerbyDialect.class)
|
||||||
|
public void testTupleReturnWithFetch(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createMutationQuery("insert Mammal (description, bodyWeight, pregnant) values ('Human', 80.0, false)").executeUpdate();
|
||||||
|
assertEquals( 1L, session.createSelectionQuery("select count(*) from Mammal").getSingleResult() );
|
||||||
|
ScrollableResults results = session.createQuery("select a, a.bodyWeight from Animal a left join fetch a.offspring").scroll();
|
||||||
|
assertTrue( results.next() );
|
||||||
|
Object[] result = (Object[]) results.get();
|
||||||
|
assertTrue(Hibernate.isInitialized(((Animal) result[0]).getOffspring()));
|
||||||
|
session.createMutationQuery("delete Mammal").executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTupleReturnWithFetchFailure(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
try {
|
||||||
|
session.createQuery( "select a.description, a.bodyWeight from Animal a inner join fetch a.offspring" ).scroll();
|
||||||
|
fail( "scroll allowed with fetch and projection result" );
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
assertTyping( SemanticException.class, e.getCause() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUknownPathFailure(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
try {
|
try {
|
||||||
session.createQuery( "select a, a.weight from Animal a inner join fetch a.offspring" ).scroll();
|
session.createQuery( "select a, a.weight from Animal a inner join fetch a.offspring" ).scroll();
|
||||||
fail( "scroll allowed with collection fetch and reurning tuples" );
|
fail( "scroll allowed with unknown path" );
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) {
|
catch (IllegalArgumentException e) {
|
||||||
assertTyping( PathElementException.class, e );
|
assertTyping( UnknownPathException.class, e.getCause() );
|
||||||
}
|
|
||||||
catch (HibernateException e) {
|
|
||||||
// expected result...
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue