fix issue with Criteria queries not defining selections explicitly. should use the (single) root as the selection.

This commit is contained in:
Steve Ebersole 2020-03-23 08:28:56 -05:00
parent ade760d71a
commit eae3a4a0a6
2 changed files with 42 additions and 7 deletions

View File

@ -51,8 +51,10 @@ import org.hibernate.query.sqm.tree.SqmDmlStatement;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.expression.SqmParameter; 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.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.query.sqm.tree.select.SqmSelection; import org.hibernate.query.sqm.tree.select.SqmSelection;
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement; import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
@ -178,16 +180,36 @@ public class QuerySqmImpl<R>
SharedSessionContractImplementor producer) { SharedSessionContractImplementor producer) {
super( producer ); super( producer );
if ( resultType != null ) {
if ( sqmStatement instanceof SqmSelectStatement ) { if ( sqmStatement instanceof SqmSelectStatement ) {
//noinspection unchecked final SqmSelectStatement sqmSelectStatement = (SqmSelectStatement) sqmStatement;
final SqmQuerySpec sqmQuerySpec = sqmSelectStatement.getQuerySpec();
final List<SqmSelection> sqmSelections = sqmQuerySpec.getSelectClause().getSelections();
// make sure there is at least one root
final List<SqmRoot> sqmRoots = sqmQuerySpec.getFromClause().getRoots();
if ( sqmRoots == null || sqmRoots.isEmpty() ) {
throw new IllegalArgumentException( "Criteria did not define any query roots" );
}
if ( sqmSelections == null || sqmSelections.isEmpty() ) {
// if there is a single root, use that as the selection
if ( sqmRoots.size() == 1 ) {
final SqmRoot sqmRoot = sqmRoots.get( 0 );
sqmQuerySpec.getSelectClause().add( sqmRoot, null );
}
else {
throw new IllegalArgumentException( );
}
}
if ( resultType != null ) {
checkQueryReturnType( (SqmSelectStatement<R>) sqmStatement, resultType, producer.getFactory() ); checkQueryReturnType( (SqmSelectStatement<R>) sqmStatement, resultType, producer.getFactory() );
} }
}
else { else {
assert sqmStatement instanceof SqmDmlStatement; assert sqmStatement instanceof SqmDmlStatement;
throw new IllegalArgumentException( "Non-select queries cannot be typed" ); throw new IllegalArgumentException( "Non-select queries cannot be typed" );
} }
}
this.hqlString = "<criteria>"; this.hqlString = "<criteria>";
this.sqmStatement = sqmStatement; this.sqmStatement = sqmStatement;

View File

@ -16,6 +16,7 @@ import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression; import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import org.hibernate.IrrelevantEntity;
import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaCriteriaQuery;
import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.criteria.JpaRoot;
@ -51,6 +52,18 @@ public class BasicCriteriaExecutionTests extends BaseNonConfigCoreFunctionalTest
); );
} }
@Test
public void testIt() {
inSession(
session -> {
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<BasicEntity> criteria = criteriaBuilder.createQuery( BasicEntity.class );
criteria.from( BasicEntity.class );
List<BasicEntity> results = session.createQuery( criteria ).list();
}
);
}
@Test @Test
public void testExecutingBasicCriteriaQueryInStatelessSession() { public void testExecutingBasicCriteriaQueryInStatelessSession() {
final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder(); final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder();