Criteria API Invalid Path generatedAlias4 with correlated subquery

I am having an invalid path issue with Hibernate and Spring JPA Criteria API. I have the following error:

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: ‘generatedAlias4.applicationId’ [select generatedAlias0 from ie.ul.ethics.scieng.applications.models.applications.Application as generatedAlias0 where :param0 in (select generatedAlias1.username from ie.ul.ethics.scieng.applications.models.applications.SubmittedApplication as generatedAlias2 inner join generatedAlias2.assignedCommitteeMembers as generatedAlias3 inner join generatedAlias3.user as generatedAlias1 where generatedAlias3.applicationId=generatedAlias4.applicationId)

Basically, the alias generatedAlias4 is presumably an alias that was meant to appear from a JOIN performed somewhere but the alias is not defined anywhere in the SQL leading to the error.

The SQL I am trying to emulate is:

SELECT a FROM SubmittedApplication a WHERE ‘test’ IN(SELECT m.username FROM SubmittedApplication a1 JOIN AssignedCommitteeMember assigned JOIN User WHERE a.applicationId = a1.applicationId);

I understand that might not be correct HQL (quickly wrote it to give a rough idea) but I am using the CriteriaQuery and CriteriaBuilder API to dynamically create the query.

The code creating the query is as follows:

    CriteriaQuery<Object> query = criteriaBuilder.createQuery();
    Root<SubmittedApplication> applicationRoot = query.from(SubmittedApplication.class);

    Subquery<String> subQuery = query.subquery(String.class);
    Root<SubmittedApplication> subApplication = subQuery.from(SubmittedApplication.class);
    Root<SubmittedApplication> correlated = subQuery.correlate(applicationRoot);

    Join<?, ?> assignedJoin = subApplication.joinList("assignedCommitteeMembers");
    Join<?, ?> assignedUserJoin = assignedJoin.join("user");
    subQuery.select(assignedUserJoin.get("username"));
    subQuery.where(criteriaBuilder.equal(assignedJoin.get("applicationId"), correlated.get("applicationId")));

    query.select(applicationRoot)
            .where(criteriaBuilder.in(criteriaBuilder.literal(criteria.getValue())).value(subQuery));

    return query.getRestriction();

It returns a Predicate for use in a Specification to search using a repository extending the JpaSpecificationExecutor interface. I used correlate to correlate the application root into the subquery, which theoretically means the last of the subquery where statement should be where generatedAlias3.applicationId=generatedAlias0.applicationId and not generatedAlias3.applicationId=generatedAlias4.applicationId

The query is meant to ask, find all Applications where the username ‘test’ exists in the list of AssignedCommitteeMembers. The SubmittedApplication class is a subclass of the Application class (a class that represents an application form being created on the system) that contains a list with OneToMany mapping of these AssignedCommitteeMembers. The first I noticed, selects from the base Application class. Shouldn’t it be selected from the SubmittedApplication class? Could this be the issue? select generatedAlias0 from ie.ul.ethics.scieng.applications.models.applications.Application as generatedAlias0 instead of select generatedAlias0 from ie.ul.ethics.scieng.applications.models.applications.SubmittedApplication as generatedAlias0

The entity for the SubmittedApplication class (with irrelevant properties stripped. The applicationId field is contained in the superclass Application. It is a String ID separate to the database ID used for application management):

@Entity
public class SubmittedApplication extends Application {
  /**
   * The list of assigned committee members
   */
  @OneToMany(cascade = CascadeType.ALL)
  protected List<AssignedCommitteeMember> assignedCommitteeMembers;
  .. other attributes
}

The AssignedCommitteeMember class is here:

@Entity
public class AssignedCommitteeMember {
  /**
   * The database ID of this object
   */
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  /**
   * The ID of the application the member is assigned to
   */
  private String applicationId;
  /**
   * The committee member that is assigned
   */
 @OneToOne
 private User user;
 /**
  * Determine if the committee member has finished their review
  */
 private boolean finishReview;

I hope I gave enough detail. If more information is needed I am happy to give it. Any help is appreciated

Thanks a lot for the details, but which Hibernate version are you using? I guess that this is a bug that you should report here though: https://hibernate.atlassian.net

Have you tried without the call to correlate to see if that makes it work?

I’m pretty sure this is fixed in 6.0 already.

Hi beikov,
Thanks for the reply. I have tried it with and without the correlate call. I am using Hibernate with Spring Boot 2.5.5 which uses the following Hibernate core version:

<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.32.Final</version>

I’m not sure if Spring is compatible with Hibernate 6, but I will give it a try and test it out. If it still doesn’t work, should I create a bug report?

It is not compatible with Hibernate 6 yet AFAIK since Hibernate 6 uses Jakarta Persistence 3.0.

Yes, please create a bug report.

Done: [HHH-15120] - Hibernate JIRA. Thanks, beikov :+1: