mirror of
https://github.com/spring-projects/spring-data-jpa.git
synced 2026-05-03 03:31:04 +01:00
Use named selection for projections to avoid AliasCollisionException.
We now use explicitly named selection items when selecting items from a projection selection to avoid name clashes through implicit naming. Signed-off-by: oualid.bouh <oualid.bouh@kleegroup.com> Closes #4135 Original pull request: #4136
This commit is contained in:
+2
-1
@@ -69,6 +69,7 @@ import org.springframework.util.Assert;
|
||||
* @author Greg Turnquist
|
||||
* @author Christoph Strobl
|
||||
* @author Jinmyeong Kim
|
||||
* @author Oualid Bouh
|
||||
*/
|
||||
public class JpaQueryCreator extends AbstractQueryCreator<String, JpqlQueryBuilder.Predicate>
|
||||
implements JpqlQueryCreator {
|
||||
@@ -299,7 +300,7 @@ public class JpaQueryCreator extends AbstractQueryCreator<String, JpqlQueryBuild
|
||||
List<JpqlQueryBuilder.Expression> paths = new ArrayList<>(requiredSelection.size());
|
||||
for (String selection : requiredSelection) {
|
||||
paths.add(JpqlUtils.toExpressionRecursively(metamodel, entity, entityType,
|
||||
PropertyPath.from(selection, returnedType.getDomainType()), true));
|
||||
PropertyPath.from(selection, returnedType.getDomainType()), true).as(selection));
|
||||
}
|
||||
|
||||
JpqlQueryBuilder.Expression distance = null;
|
||||
|
||||
+45
@@ -65,6 +65,7 @@ import org.springframework.data.util.Lazy;
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Oualid Bouh
|
||||
*/
|
||||
class JpaQueryCreatorTests {
|
||||
|
||||
@@ -76,6 +77,9 @@ class JpaQueryCreatorTests {
|
||||
|
||||
static List<JpqlQueryTemplates> ignoreCaseTemplates = List.of(JpqlQueryTemplates.LOWER, JpqlQueryTemplates.UPPER);
|
||||
|
||||
private static final TestMetaModel ORDER_WITH_RELATIONS = TestMetaModel.hibernateModel(
|
||||
OrderWithRelations.class, Customer.class, Supplier.class);
|
||||
|
||||
@Test // GH-3588
|
||||
void simpleProperty() {
|
||||
|
||||
@@ -1131,4 +1135,45 @@ class JpaQueryCreatorTests {
|
||||
return queryCreator(partTree, returnedType, metamodel, queryTemplates, parameterAccessor.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test // GH-4135
|
||||
void interfaceProjectionWithMultipleJoinsShouldGenerateUniqueAliases() {
|
||||
|
||||
queryCreator(ORDER_WITH_RELATIONS)
|
||||
.forTree(OrderWithRelations.class, "findProjectionById")
|
||||
.returning(OrderSummaryProjection.class)
|
||||
.withParameters(1L)
|
||||
.as(QueryCreatorTester::create)
|
||||
.expectJpql(
|
||||
"SELECT o.id id, c.id customerId, s.id supplierId, c.name customerName, s.name supplierName FROM %s o LEFT JOIN o.customer c LEFT JOIN o.supplier s WHERE o.id = ?1",
|
||||
DefaultJpaEntityMetadata.unqualify(OrderWithRelations.class))
|
||||
.validateQuery();
|
||||
}
|
||||
|
||||
@jakarta.persistence.Entity
|
||||
static class OrderWithRelations {
|
||||
@Id Long id;
|
||||
@ManyToOne Customer customer;
|
||||
@ManyToOne Supplier supplier;
|
||||
}
|
||||
|
||||
@jakarta.persistence.Entity
|
||||
static class Customer {
|
||||
@Id Long id;
|
||||
String name;
|
||||
}
|
||||
|
||||
@jakarta.persistence.Entity
|
||||
static class Supplier {
|
||||
@Id Long id;
|
||||
String name;
|
||||
}
|
||||
|
||||
interface OrderSummaryProjection {
|
||||
Long getId();
|
||||
Long getCustomerId(); // → customer.id
|
||||
Long getSupplierId(); // → supplier.id
|
||||
String getCustomerName(); // → customer.name
|
||||
String getSupplierName(); // → supplier.name
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user