Description:
When a repository's SELECT target type differs from its FROM (root) entity type (e.g. EntityRepository<Tenant, Int>.select(Owner::class)), Storm builds the SELECT column list from the target type's model. The expanded column metamodels are
rooted at the SELECT target (Owner), with paths like address.city. The alias mapper, however, has registered every auto-joined table with paths rooted at the FROM table (Tenant): owner, owner.address.city, city, etc.
In QueryModelImpl.toColumnExpression, the path-specific lookup findAlias(City.class, "address.city", INNER) finds no match (registered paths are owner.address.city and city). It falls back to findAlias(City.class, null, INNER), which considers
all entries for City regardless of path — and throws Multiple aliases found for: City. whenever the same table is reachable through more than one branch of the FROM tree.
Reproduction:
record Tenant(
@PK Integer id,
@Nonnull String name,
@Nonnull @FK Owner owner,
@Nonnull @FK City city
) implements Entity<Integer> {}
// Owner already has @FK City via its inline Address.
EntityRepository<Tenant, Integer> tenants = orm.entity(Tenant.class);
List<Owner> owners = tenants.select(Owner.class).getResultList();
The entity graph contains two paths to City:
- Tenant → Owner → Address.city
- Tenant → city
Expected: the SELECT target's expanded City columns resolve via the owner.address.city branch (the only branch reachable from the SELECT target).
Actual: st.orm.core.template.SqlTemplateException: Multiple aliases found for: City.
Stack:
AliasMapper.multipleFoundException(AliasMapper.java:121)
AliasMapper.findAlias(AliasMapper.java:246)
QueryModelImpl.toColumnExpression(QueryModelImpl.java:615)
QueryModelImpl.getColumns(QueryModelImpl.java:148)
SelectProcessor.compile(SelectProcessor.java:55)
Fix: in toColumnExpression, when metamodel.root() != model.type(), look up the single registered path for metamodel.root() in the alias map and prepend it before lookup — translating SELECT-target-rooted paths (address.city) into FROM-rooted
paths (owner.address.city). The WHERE clause is unaffected (its metamodels are already rooted at the FROM table).
Description:
When a repository's SELECT target type differs from its FROM (root) entity type (e.g. EntityRepository<Tenant, Int>.select(Owner::class)), Storm builds the SELECT column list from the target type's model. The expanded column metamodels are
rooted at the SELECT target (Owner), with paths like address.city. The alias mapper, however, has registered every auto-joined table with paths rooted at the FROM table (Tenant): owner, owner.address.city, city, etc.
In QueryModelImpl.toColumnExpression, the path-specific lookup findAlias(City.class, "address.city", INNER) finds no match (registered paths are owner.address.city and city). It falls back to findAlias(City.class, null, INNER), which considers
all entries for City regardless of path — and throws Multiple aliases found for: City. whenever the same table is reachable through more than one branch of the FROM tree.
Reproduction:
The entity graph contains two paths to City:
Expected: the SELECT target's expanded City columns resolve via the owner.address.city branch (the only branch reachable from the SELECT target).
Actual: st.orm.core.template.SqlTemplateException: Multiple aliases found for: City.
Stack:
Fix: in toColumnExpression, when metamodel.root() != model.type(), look up the single registered path for metamodel.root() in the alias map and prepend it before lookup — translating SELECT-target-rooted paths (address.city) into FROM-rooted
paths (owner.address.city). The WHERE clause is unaffected (its metamodels are already rooted at the FROM table).