further work on query parser exceptions

I missed a couple of things
This commit is contained in:
Gavin King 2023-06-13 21:29:06 +02:00
parent d859f43748
commit 9adffa4e4f
24 changed files with 198 additions and 100 deletions

View File

@ -7,8 +7,22 @@
package org.hibernate;
/**
* A problem occurred translating a Hibernate query to SQL
* due to invalid query syntax, or some similar problem.
* A problem occurred translating a Hibernate query to SQL due to illegal query
* 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 {
private final String queryString;

View File

@ -8,7 +8,7 @@ package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.metamodel.model.domain.BasicDomainType;
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.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath;

View File

@ -47,7 +47,7 @@ import org.hibernate.metamodel.model.domain.ManagedDomainType;
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
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.service.ServiceRegistry;
import org.hibernate.type.descriptor.java.EnumJavaType;
@ -164,7 +164,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
public <X> EntityDomainType<X> resolveHqlEntityReference(String entityName) {
final EntityDomainType<X> hqlEntityReference = getHqlEntityReference( entityName );
if ( hqlEntityReference == null ) {
throw new EntityReferenceException( "Could not resolve entity reference: " + entityName );
throw new EntityTypeException( "Could not resolve entity name '" + entityName + "'", entityName );
}
return hqlEntityReference;
}
@ -444,7 +444,8 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
// 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 ) {
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

View File

@ -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);
}
}

View File

@ -13,7 +13,10 @@ import java.util.Map;
/**
* 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
*/

View File

@ -7,23 +7,22 @@
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
*
* @see PathElementException
* @see TerminalPathException
* @see org.hibernate.query.sqm.UnknownPathException
*/
public class PathException extends SemanticException {
public PathException(String message) {
super( message );
}
/**
* @deprecated This is currently unused
*/
@Deprecated(forRemoval = true, since = "6.3")
public PathException(String message, Exception cause) {
super( message, cause );
}
public PathException(String message, String hql, Exception cause) {
super(message, hql, cause);
}
}

View File

@ -9,7 +9,7 @@ package org.hibernate.query;
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
*/

View File

@ -9,10 +9,12 @@ package org.hibernate.query;
import org.hibernate.QueryException;
/**
* Indicates a request for a named-query when no query is
* registered under that name
* Occurs when a named query is requested, and there is no known
* HQL or native SQL query registered under the given name.
*
* @author Steve Ebersole
*
* @see org.hibernate.query.named.NamedObjectRepository
*/
public class UnknownNamedQueryException extends QueryException {
public UnknownNamedQueryException(String queryName) {

View File

@ -57,7 +57,7 @@ import org.hibernate.query.ParameterLabelException;
import org.hibernate.query.PathException;
import org.hibernate.query.ReturnableType;
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.JpaCteCriteriaAttribute;
import org.hibernate.query.criteria.JpaCteCriteriaType;

View File

@ -14,15 +14,17 @@ import org.antlr.v4.runtime.NoViableAltException;
import org.hibernate.QueryException;
import org.hibernate.grammars.hql.HqlLexer;
import org.hibernate.grammars.hql.HqlParser;
import org.hibernate.query.EntityReferenceException;
import org.hibernate.query.PathElementException;
import org.hibernate.query.sqm.EntityTypeException;
import org.hibernate.query.sqm.PathElementException;
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.HqlTranslator;
import org.hibernate.query.hql.spi.SqmCreationOptions;
import org.hibernate.query.sqm.InterpretationException;
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.spi.SqmCreationContext;
import org.hibernate.query.sqm.tree.SqmStatement;
@ -78,9 +80,15 @@ public class StandardHqlTranslator implements HqlTranslator {
return sqmStatement;
}
catch (QueryException | PathElementException | TerminalPathException | EntityReferenceException e) {
catch (QueryException 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) {
// this is some sort of "unexpected" exception, i.e. something buglike
throw new InterpretationException( query, e );

View File

@ -11,6 +11,7 @@ import java.util.Map;
import java.util.function.Consumer;
import org.hibernate.HibernateException;
import org.hibernate.QueryException;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
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.engine.spi.SessionFactoryImplementor;
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.PathElementException;
import org.hibernate.query.TerminalPathException;
import org.hibernate.query.sqm.PathElementException;
import org.hibernate.query.sqm.TerminalPathException;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryInterpretationCache;
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.jboss.logging.Logger;
@ -239,21 +242,24 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
// Check named HQL queries
log.debugf( "Checking %s named HQL queries", sqmMementoMap.size() );
for ( NamedSqmQueryMemento hqlMemento : sqmMementoMap.values() ) {
final String queryString = hqlMemento.getHqlString();
final String registrationName = hqlMemento.getRegistrationName();
try {
log.debugf( "Checking named HQL query: %s", hqlMemento.getRegistrationName() );
String queryString = hqlMemento.getHqlString();
log.debugf( "Checking named HQL query: %s", registrationName );
interpretationCache.resolveHqlInterpretation(
queryString,
null,
s -> queryEngine.getHqlTranslator().translate( queryString, null )
);
}
catch ( HibernateException e ) {
errors.put( hqlMemento.getRegistrationName(), e );
catch ( QueryException e ) {
errors.put( registrationName, e );
}
catch ( PathElementException | TerminalPathException | EntityReferenceException e ) {
// JPA does not let these be HibernateExceptions in general
errors.put( hqlMemento.getRegistrationName(), new HibernateException(e) );
catch ( PathElementException | TerminalPathException e ) {
errors.put( registrationName, new UnknownPathException( e.getMessage(), queryString, e ) );
}
catch ( EntityTypeException e ) {
errors.put( registrationName, new UnknownEntityException( e.getMessage(), e.getReference(), e ) );
}
}

View File

@ -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;
}
}

View File

@ -4,15 +4,15 @@
* 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;
package org.hibernate.query.sqm;
/**
* Indicates that an element of a path did not resolve to
* a mapped program element.
*
* @apiNote extends {@link IllegalArgumentException} to
* satisfy a questionable requirement of the JPA criteria
* query API
* satisfy a questionable requirement of the JPA
* criteria query API
*
* @since 6.3
*

View File

@ -11,7 +11,6 @@ import java.util.Locale;
import jakarta.persistence.metamodel.Bindable;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.PathElementException;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.tree.SqmExpressibleAccessor;
import org.hibernate.query.sqm.tree.domain.SqmPath;

View File

@ -4,15 +4,15 @@
* 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;
package org.hibernate.query.sqm;
/**
* Indicates an attempt to dereference a terminal path
* (usually a path referring to something of basic type)
*
* @apiNote extends {@link IllegalStateException} to
* satisfy a questionable requirement of the JPA criteria
* query API
* satisfy a questionable requirement of the JPA
* criteria query API
*
* @since 6.3
*

View File

@ -9,14 +9,18 @@ package org.hibernate.query.sqm;
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
* {@link IllegalArgumentException}.
*
* todo (6.0) : account for this in the "exception conversion" handling
* @apiNote The JPA criteria API requires that this problem be reported
* as an {@link IllegalArgumentException}, and so we usually
* throw {@link EntityTypeException} 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
*
* @see EntityTypeException
*/
public class UnknownEntityException extends SemanticException {
private final String entityName;
@ -30,6 +34,11 @@ public class UnknownEntityException extends SemanticException {
this.entityName = entityName;
}
public UnknownEntityException(String message, String entityName, Exception cause) {
super( message, cause );
this.entityName = entityName;
}
public String getEntityName() {
return entityName;
}

View File

@ -8,30 +8,44 @@ package org.hibernate.query.sqm;
import java.util.Locale;
import org.hibernate.query.SemanticException;
import org.hibernate.query.PathException;
import org.hibernate.query.sqm.tree.domain.SqmPath;
/**
* Indicates a failure to resolve an element of a path expression in HQL/JPQL.
*
*
* todo (6.0) : account for this in the "exception conversion" handling
* @apiNote The JPA criteria API requires that this sort of problem be reported
* 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
*
* @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) {
return new UnknownPathException(
String.format(
Locale.ROOT,
"Could not resolve path `%s` relative to %s (%s)",
"Could not resolve path element '%s' relative to '%s' (%s)",
name,
base.getReferencedPathSource().getSqmPathType().getTypeName(),
base.getNavigablePath()
)
);
}
private UnknownPathException(String message) {
super( message );
}
}

View File

@ -19,6 +19,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.PathException;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmStatement;
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(

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.tree.domain;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.PathException;
import org.hibernate.query.hql.spi.SqmCreationState;
@ -70,7 +71,7 @@ public class SqmBasicValuedSimplePath<T>
String name,
boolean isTerminal,
SqmCreationState creationState) {
throw new PathException(
throw new UnknownPathException(
String.format(
"Could not interpret attribute '%s' of basic-valued path '%s'",
name, getNavigablePath()

View File

@ -16,7 +16,7 @@ import jakarta.persistence.metamodel.PluralAttribute;
import jakarta.persistence.metamodel.SingularAttribute;
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.query.criteria.JpaPath;
import org.hibernate.query.hql.spi.SemanticPathPart;
@ -138,7 +138,7 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
SqmExpression<?> selector,
boolean isTerminal,
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

View File

@ -90,7 +90,7 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
String name,
boolean isTerminal,
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 );
if ( nature == null ) {
throw new PathException( "Plural path '" + getNavigablePath()

View File

@ -10,12 +10,12 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Locale;
import org.hibernate.query.PathException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
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.domain.SqmPath;
import org.hibernate.type.descriptor.java.EnumJavaType;
@ -85,7 +85,7 @@ public class SqmEnumLiteral<E extends Enum<E>> extends AbstractSqmExpression<E>
String name,
boolean isTerminal,
SqmCreationState creationState) {
throw new PathException(
throw new UnknownPathException(
String.format(
Locale.ROOT,
"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,
boolean isTerminal,
SqmCreationState creationState) {
throw new PathException(
throw new UnknownPathException(
String.format(
Locale.ROOT,
"Static enum reference [%s#%s] cannot be de-referenced",

View File

@ -14,14 +14,13 @@ import java.util.List;
import java.util.Locale;
import org.hibernate.QueryException;
import org.hibernate.query.PathException;
import org.hibernate.query.SemanticException;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
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.domain.SqmPath;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
@ -229,7 +228,7 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
String name,
boolean isTerminal,
SqmCreationState creationState) {
throw new PathException(
throw new UnknownPathException(
String.format(
Locale.ROOT,
"Static field reference [%s#%s] cannot be de-referenced",
@ -244,7 +243,7 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
SqmExpression<?> selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new PathException(
throw new UnknownPathException(
String.format(
Locale.ROOT,
"Static field reference [%s#%s] cannot be de-referenced",

View File

@ -6,13 +6,16 @@
*/
package org.hibernate.orm.test.hql;
import org.hibernate.HibernateException;
import org.hibernate.Hibernate;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
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.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
@ -43,22 +46,51 @@ import static org.junit.jupiter.api.Assertions.fail;
public class ScrollableCollectionFetchingTest {
@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(
session -> {
try {
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) {
assertTyping( PathElementException.class, e );
}
catch (HibernateException e) {
// expected result...
assertTyping( UnknownPathException.class, e.getCause() );
}
}
);
}
@Test