Skip to content

Commit c5addc7

Browse files
committed
Avoid JPQL selection aliasing by default.
We now no longer apply an alias for property paths within the selection list unless required aliases when using tuple queries to materialize projections. Also, we now add correctly the AS keyword between the selection and the alias to remain spec-compliant. Closes #4167
1 parent dc10e4e commit c5addc7

File tree

5 files changed

+21
-28
lines changed

5 files changed

+21
-28
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryCreator.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,8 @@ private JpqlQueryBuilder.Select doSelect(Sort sort) {
288288

289289
if (returnedType.needsCustomConstruction()) {
290290

291-
Collection<String> requiredSelection = null;
291+
boolean tupleQuery = useTupleQuery();
292+
Collection<String> requiredSelection;
292293
if (returnedType.getReturnedType().getPackageName().startsWith("java.util")
293294
|| returnedType.getReturnedType().getPackageName().startsWith("jakarta.persistence")) {
294295
requiredSelection = metamodel.managedType(returnedType.getDomainType()).getAttributes().stream()
@@ -299,16 +300,17 @@ private JpqlQueryBuilder.Select doSelect(Sort sort) {
299300

300301
List<JpqlQueryBuilder.Expression> paths = new ArrayList<>(requiredSelection.size());
301302
for (String selection : requiredSelection) {
302-
paths.add(JpqlUtils.toExpressionRecursively(metamodel, entity, entityType,
303-
PropertyPath.from(selection, returnedType.getDomainType()), true).as(selection));
303+
JpqlQueryBuilder.PathExpression expression = JpqlUtils.toExpressionRecursively(metamodel, entity, entityType,
304+
PropertyPath.from(selection, returnedType.getDomainType()), true);
305+
paths.add(tupleQuery ? expression.as(selection) : expression);
304306
}
305307

306308
JpqlQueryBuilder.Expression distance = null;
307309
if (searchQuery) {
308310
distance = getDistanceExpression();
309311
}
310312

311-
if (useTupleQuery()) {
313+
if (tupleQuery) {
312314

313315
if (searchQuery) {
314316
paths.add((distance != null ? distance : JpqlQueryBuilder.literal(0)).as("distance"));

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpqlQueryBuilder.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,17 @@ default Select select(JpqlQueryBuilder.PathExpression path) {
521521

522522
}
523523

524+
/**
525+
* Interface specifying a selection that can be rendered to {@code String}.
526+
*/
524527
public interface Selection {
525528

529+
/**
530+
* Render the selection given {@link RenderContext} to string.
531+
*
532+
* @param context
533+
* @return the rendered selection.
534+
*/
526535
String render(RenderContext context);
527536

528537
}
@@ -658,7 +667,7 @@ public String render(RenderContext context) {
658667

659668
builder.append(path.render(context));
660669
if (!context.isConstructorContext() && path instanceof AliasedExpression ae) {
661-
builder.append(" ").append(ae.getAlias());
670+
builder.append(" AS ").append(ae.getAlias());
662671
}
663672
}
664673

@@ -1541,7 +1550,7 @@ public String toString() {
15411550
* @param onTheJoin whether the path should target the join itself instead of matching {@link PropertyPath}.
15421551
*/
15431552
record PathAndOrigin(PropertyPath path, Origin origin,
1544-
boolean onTheJoin) implements PathExpression, AliasedExpression {
1553+
boolean onTheJoin) implements PathExpression {
15451554

15461555
@Override
15471556
public PropertyPath getPropertyPath() {
@@ -1558,11 +1567,6 @@ public String render(RenderContext context) {
15581567
}
15591568
}
15601569

1561-
@Override
1562-
public String getAlias() {
1563-
return path().getSegment();
1564-
}
1565-
15661570
}
15671571

15681572
/**

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkNamespaceUserRepositoryTests.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,6 @@ public void modifyingUpdateNativeQueryWorksWithJSQLParser() {}
186186
@Test
187187
public void scrollByPredicateKeysetWithInterfaceProjection() {}
188188

189-
@Disabled("EclipseLink treats id as keyword")
190-
@Override
191-
@Test
192-
public void executesDerivedExistsQuery() {}
193-
194189
@Disabled("Not spec-compliant")
195190
@Override
196191
@Test

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkUserRepositoryFinderTests.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,6 @@
2828
@ContextConfiguration("classpath:eclipselink-h2.xml")
2929
class EclipseLinkUserRepositoryFinderTests extends UserRepositoryFinderTests {
3030

31-
@Disabled
32-
@Override
33-
void executesNotInQueryCorrectly() {}
34-
35-
@Disabled
36-
@Override
37-
void executesInKeywordForPageCorrectly() {}
38-
3931
@Disabled
4032
@Override
4133
void shouldProjectWithKeysetScrolling() {}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryCreatorTests.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ void interfaceProjection() {
707707
.returning(InterfaceProductProjection.class) //
708708
.withParameters("spring") //
709709
.as(QueryCreatorTester::create) //
710-
.expectJpql("SELECT p.name name, p.productType productType FROM %s p WHERE p.name = ?1",
710+
.expectJpql("SELECT p.name AS name, p.productType AS productType FROM %s p WHERE p.name = ?1",
711711
DefaultJpaEntityMetadata.unqualify(Product.class)) //
712712
.validateQuery();
713713
}
@@ -722,7 +722,7 @@ void tupleProjection(Class<?> resultType) {
722722
.withParameters("chris") //
723723
.as(QueryCreatorTester::create) //
724724
.expectJpql(
725-
"SELECT p.id id, p.emailAddress emailAddress, p.firstname firstname, p.lastname lastname FROM %s p WHERE p.firstname = ?1",
725+
"SELECT p.id AS id, p.emailAddress AS emailAddress, p.firstname AS firstname, p.lastname AS lastname FROM %s p WHERE p.firstname = ?1",
726726
DefaultJpaEntityMetadata.unqualify(Person.class)) //
727727
.validateQuery();
728728
}
@@ -747,7 +747,7 @@ void exists() {
747747
.forTree(Person.class, "existsPersonByFirstname") //
748748
.returning(Long.class).withParameters("chris") //
749749
.as(QueryCreatorTester::create) //
750-
.expectJpql("SELECT p.id id FROM %s p WHERE p.firstname = ?1", DefaultJpaEntityMetadata.unqualify(Person.class)) //
750+
.expectJpql("SELECT p.id FROM %s p WHERE p.firstname = ?1", DefaultJpaEntityMetadata.unqualify(Person.class)) //
751751
.validateQuery();
752752
}
753753

@@ -1142,7 +1142,7 @@ void interfaceProjectionShouldGenerateUniqueSelectionAliases() {
11421142
.withParameters(1L) //
11431143
.as(QueryCreatorTester::create) //
11441144
.expectJpql(
1145-
"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",
1145+
"SELECT o.id AS id, c.id AS customerId, s.id AS supplierId, c.name AS customerName, s.name AS supplierName FROM %s o LEFT JOIN o.customer c LEFT JOIN o.supplier s WHERE o.id = ?1",
11461146
DefaultJpaEntityMetadata.unqualify(OrderWithRelations.class))
11471147
.validateQuery();
11481148
}

0 commit comments

Comments
 (0)