Oleksii Miroshnyk ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=5a157d9... ) *created* an issue
Bean Validation ( https://hibernate.atlassian.net/browse/BVAL?atlOrigin=eyJpIjoiY2E1NjljMmZ... ) / Bug ( https://hibernate.atlassian.net/browse/BVAL-787?atlOrigin=eyJpIjoiY2E1Njl... ) BVAL-787 ( https://hibernate.atlassian.net/browse/BVAL-787?atlOrigin=eyJpIjoiY2E1Njl... ) Alias XXX used for multiple from-clause elements error when executing query with 2 level join ( https://hibernate.atlassian.net/browse/BVAL-787?atlOrigin=eyJpIjoiY2E1Njl... )
Issue Type: Bug Assignee: Unassigned Created: 10/May/2023 08:22 AM Environment: java 17, spring boot 3, hibernate 6.1.7 Priority: Blocker Reporter: Oleksii Miroshnyk ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=5a157d9... )
Seems there is a bug somewhere either in query parsing or joins processing in hibernate 6.1.7+
That code & query works fine in all prev. versions from hibernate 3 to 5
I have a named query:
```
<query>SELECT COUNT(adminPermission)
FROM org.broadleafcommerce.openadmin.server.security.domain.AdminPermission adminPermission
LEFT OUTER JOIN adminPermission.allChildPermissions childPermission
LEFT OUTER JOIN childPermission.qualifiedEntities childQualifiedEntity
LEFT OUTER JOIN adminPermission.qualifiedEntities qualifiedEntity
LEFT OUTER JOIN adminPermission.allRoles role
LEFT OUTER JOIN role.allUsers roleUser
LEFT OUTER JOIN adminPermission.allUsers permissionUser
WHERE (roleUser = :adminUser OR permissionUser = :adminUser) AND
(adminPermission.type = :type OR adminPermission.type = 'ALL' OR
childPermission.type = :type OR childPermission.type = 'ALL') AND
(qualifiedEntity.ceilingEntityFullyQualifiedName = :ceilingEntity OR childQualifiedEntity.ceilingEntityFullyQualifiedName = :ceilingEntity)
</query>
```
There OneToMany and ManyToMany through JoinTable asossiations it this is important
I debugged a bit and see that it processes condition (roleUser = :adminUser OR permissionUser = :adminUser)
and finds a join
LEFT OUTER JOIN role.allUsers roleUser
so it finds alias "roleUser", logic goes into
org.hibernate.query.hql.internal.QuerySplitter.UnmappedPolymorphismReplacer#visitSetJoin
where it does:
final SqmSetJoin copy = new SqmSetJoin<>(
findSqmFromCopy( join.getLhs() ),
so join.getLhs() will return another join
LEFT OUTER JOIN adminPermission.allRoles role
so it finds alias "role"
And in org.hibernate.query.hql.internal.QuerySplitter.UnmappedPolymorphismReplacer#findSqmFromCopy
it does
return (X) sqmFrom.accept( this );
So it will do a recursive call that will eventually come to org.hibernate.query.hql.internal.QuerySplitter.UnmappedPolymorphismReplacer#visitSetJoin again, where it will process join with alias "role" and in
org.hibernate.query.hql.internal.QuerySplitter.UnmappedPolymorphismReplacer#visitJoins
will register that alias, and also it will do
join.visitSqmJoins(
sqmJoin ->
sqmJoin.accept( this )
);
where "role" join will reference "roleUser" join via joins.forEach( consumer ); in
org.hibernate.query.sqm.tree.domain.AbstractSqmFrom#visitSqmJoins
it will process it and also registers via org.hibernate.query.hql.internal.SqmPathRegistryImpl#register(org.hibernate.query.sqm.tree.domain.SqmPath<?>)
so now registry map knows about "role" and "roleUser" joins and recursion ends and it eventually continues to process "roleUse" join - where we start recursion... and it again will attempt to register
org.hibernate.query.hql.internal.SqmPathRegistryImpl#register(org.hibernate.query.sqm.tree.domain.SqmPath<?>)
where it fails with exception... So there is something wrong on how "multi-level joins" are handled.
( https://hibernate.atlassian.net/browse/BVAL-787#add-comment?atlOrigin=eyJ... ) Add Comment ( https://hibernate.atlassian.net/browse/BVAL-787#add-comment?atlOrigin=eyJ... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100225- sha1:55ea0c5 )