diff --git a/pom.xml b/pom.xml
index 1847f4d2c4..bc0025bd35 100755
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.5.0-SNAPSHOT
+ 3.5.x-GH-3726-SNAPSHOT
pom
Spring Data JPA Parent
@@ -30,7 +30,7 @@
4.13.0
4.0.4
4.0.5-SNAPSHOT
- 6.6.2.Final
+ 6.6.4.Final
6.2.31.Final
6.6.3-SNAPSHOT
7.0.0.Beta1
diff --git a/spring-data-envers/pom.xml b/spring-data-envers/pom.xml
index 5dcbbb69fd..a3a40ac100 100755
--- a/spring-data-envers/pom.xml
+++ b/spring-data-envers/pom.xml
@@ -5,12 +5,12 @@
org.springframework.data
spring-data-envers
- 3.5.0-SNAPSHOT
+ 3.5.x-GH-3726-SNAPSHOT
org.springframework.data
spring-data-jpa-parent
- 3.5.0-SNAPSHOT
+ 3.5.x-GH-3726-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa-distribution/pom.xml b/spring-data-jpa-distribution/pom.xml
index 38a234cb71..ebf928fbaf 100644
--- a/spring-data-jpa-distribution/pom.xml
+++ b/spring-data-jpa-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.5.0-SNAPSHOT
+ 3.5.x-GH-3726-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml
index c6d9301c02..fba223beb2 100644
--- a/spring-data-jpa/pom.xml
+++ b/spring-data-jpa/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-jpa
- 3.5.0-SNAPSHOT
+ 3.5.x-GH-3726-SNAPSHOT
Spring Data JPA
Spring Data module for JPA repositories.
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.5.0-SNAPSHOT
+ 3.5.x-GH-3726-SNAPSHOT
../pom.xml
@@ -98,6 +98,12 @@
junit-platform-launcher
test
+
+ org.junit-pioneer
+ junit-pioneer
+ 2.3.0
+ test
+
org.hsqldb
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java
index 735bdae29c..6a12eb6e56 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java
@@ -17,6 +17,8 @@
import static org.springframework.data.jpa.repository.query.QueryTokens.*;
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.springframework.data.jpa.repository.query.HqlParser.CteContext;
import org.springframework.data.jpa.repository.query.HqlParser.SelectClauseContext;
import org.springframework.data.jpa.repository.query.QueryRenderer.QueryRendererBuilder;
import org.springframework.data.jpa.repository.query.QueryTransformers.CountSelectionTokenStream;
@@ -36,6 +38,7 @@ class HqlCountQueryTransformer extends HqlQueryRenderer {
private final @Nullable String countProjection;
private final @Nullable String primaryFromAlias;
+ private boolean containsCTE = false;
HqlCountQueryTransformer(@Nullable String countProjection, @Nullable String primaryFromAlias) {
this.countProjection = countProjection;
@@ -66,6 +69,12 @@ public QueryRendererBuilder visitOrderedQuery(HqlParser.OrderedQueryContext ctx)
return builder;
}
+ @Override
+ public QueryTokenStream visitCte(CteContext ctx) {
+ this.containsCTE = true;
+ return super.visitCte(ctx);
+ }
+
@Override
public QueryRendererBuilder visitFromQuery(HqlParser.FromQueryContext ctx) {
@@ -189,7 +198,9 @@ public QueryTokenStream visitSelectClause(HqlParser.SelectClauseContext ctx) {
nested.append(QueryTokens.expression(ctx.DISTINCT()));
nested.append(getDistinctCountSelection(visit(ctx.selectionList())));
} else {
- nested.append(QueryTokens.token(primaryFromAlias));
+ // with CTE primary alias erors with hibernate
+ nested.append(containsCTE ? QueryTokens.token("*") : QueryTokens.token(primaryFromAlias));
+// nested.append(QueryTokens.token(primaryFromAlias));
}
} else {
builder.append(QueryTokens.token(countProjection));
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java
index 16fa3c30e0..1fc5c31663 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java
@@ -18,6 +18,7 @@
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
+import org.springframework.core.SpringProperties;
import org.springframework.data.jpa.repository.QueryRewriter;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.ValueExpressionDelegate;
@@ -84,6 +85,10 @@ private void validateQuery(String query, String errorMessage, Object... argument
return;
}
+ if(SpringProperties.getFlag("spring.jpa.query.validation.disbaled")) {
+ return;
+ }
+
EntityManager validatingEm = null;
try {
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkEntityGraphRepositoryMethodsIntegrationTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkEntityGraphRepositoryMethodsIntegrationTests.java
index e0d21dc716..17d6e7771f 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkEntityGraphRepositoryMethodsIntegrationTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkEntityGraphRepositoryMethodsIntegrationTests.java
@@ -17,6 +17,7 @@
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.SetSystemProperty;
import org.springframework.test.context.ContextConfiguration;
/**
@@ -24,6 +25,7 @@
* @author Christoph Strobl
*/
@ContextConfiguration("classpath:eclipselink.xml")
+@SetSystemProperty(key = "spring.jpa.query.validation.disbaled", value = "true")
class EclipseLinkEntityGraphRepositoryMethodsIntegrationTests
extends EntityGraphRepositoryMethodsIntegrationTests {
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkParentRepositoryIntegrationTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkParentRepositoryIntegrationTests.java
index 06d1575fd5..52a8dad60f 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkParentRepositoryIntegrationTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkParentRepositoryIntegrationTests.java
@@ -15,9 +15,11 @@
*/
package org.springframework.data.jpa.repository;
+import org.junitpioneer.jupiter.SetSystemProperty;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration("classpath:eclipselink.xml")
+@SetSystemProperty(key = "spring.jpa.query.validation.disbaled", value = "true")
class EclipseLinkParentRepositoryIntegrationTests extends ParentRepositoryIntegrationTests {
}
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkRepositoryWithCompositeKeyIntegrationTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkRepositoryWithCompositeKeyIntegrationTests.java
index 82ca0c59a9..eba90ffcfb 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkRepositoryWithCompositeKeyIntegrationTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkRepositoryWithCompositeKeyIntegrationTests.java
@@ -15,6 +15,7 @@
*/
package org.springframework.data.jpa.repository;
+import org.junitpioneer.jupiter.SetSystemProperty;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
@@ -24,6 +25,7 @@
* @author Mark Paluch
*/
@ContextConfiguration
+@SetSystemProperty(key = "spring.jpa.query.validation.disbaled", value = "true")
class EclipseLinkRepositoryWithCompositeKeyIntegrationTests extends RepositoryWithIdClassKeyTests {
@ImportResource({ "classpath:infrastructure.xml", "classpath:eclipselink.xml" })
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkUserRepositoryFinderTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkUserRepositoryFinderTests.java
index 18e0570de8..07953bf97f 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkUserRepositoryFinderTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkUserRepositoryFinderTests.java
@@ -16,6 +16,7 @@
package org.springframework.data.jpa.repository;
import org.junit.jupiter.api.Disabled;
+import org.junitpioneer.jupiter.SetSystemProperty;
import org.springframework.test.context.ContextConfiguration;
/**
@@ -26,6 +27,7 @@
* @author Greg Turnquist
*/
@ContextConfiguration("classpath:eclipselink-h2.xml")
+@SetSystemProperty(key = "spring.jpa.query.validation.disbaled", value = "true")
class EclipseLinkUserRepositoryFinderTests extends UserRepositoryFinderTests {
@Disabled
@@ -40,4 +42,9 @@ void executesInKeywordForPageCorrectly() {}
@Override
void rawMapProjectionWithEntityAndAggregatedValue() {}
+ @Disabled
+ @Override
+ void testQueryWithCTE() {
+ super.testQueryWithCTE();
+ }
}
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java
index 09281ed623..ecc14cd3d1 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java
@@ -47,6 +47,7 @@
import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.provider.PersistenceProvider;
import org.springframework.data.jpa.repository.sample.RoleRepository;
+import org.springframework.data.jpa.repository.sample.UserExcerptDto;
import org.springframework.data.jpa.repository.sample.UserRepository;
import org.springframework.data.jpa.repository.sample.UserRepository.IdOnly;
import org.springframework.data.jpa.repository.sample.UserRepository.NameOnly;
@@ -433,6 +434,13 @@ void dtoMultiselectProjectionShouldApplyConstructorExpressionRewriting() {
.contains("Dave", "Carter", "Oliver August");
}
+ @Test // GH-3726
+ void testQueryWithCTE() {
+
+ Page result = userRepository.findWithCTE(PageRequest.of(0, 1));
+ assertThat(result.getTotalElements()).isEqualTo(3);
+ }
+
@Test // GH-3076
void dynamicDtoProjection() {
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkJpa21UtilsTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkJpa21UtilsTests.java
index bd97fbb600..d87bdf8034 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkJpa21UtilsTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkJpa21UtilsTests.java
@@ -15,10 +15,12 @@
*/
package org.springframework.data.jpa.repository.query;
+import org.junitpioneer.jupiter.SetSystemProperty;
import org.springframework.test.context.ContextConfiguration;
/**
* @author Christoph Strobl
*/
@ContextConfiguration("classpath:eclipselink.xml")
+@SetSystemProperty(key = "spring.jpa.query.validation.disbaled", value = "true")
class EclipseLinkJpa21UtilsTests extends Jpa21UtilsTests {}
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkMetaAnnotatedQueryMethodIntegrationTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkMetaAnnotatedQueryMethodIntegrationTests.java
index df7b27f9d9..8427549b20 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkMetaAnnotatedQueryMethodIntegrationTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkMetaAnnotatedQueryMethodIntegrationTests.java
@@ -33,6 +33,7 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junitpioneer.jupiter.SetSystemProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -69,6 +70,7 @@
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@Transactional
+@SetSystemProperty(key = "spring.jpa.query.validation.disbaled", value = "true")
class EclipseLinkMetaAnnotatedQueryMethodIntegrationTests {
@Autowired RoleRepositoryWithMeta repository;
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java
index 2ee28f804a..026aaedd27 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java
@@ -539,7 +539,7 @@ WITH maxId AS(select max(sr.snapshot.id) snapshotId from SnapshotReference sr
""");
assertThat(countQuery).startsWith("WITH maxId AS (select max(sr.snapshot.id) snapshotId from SnapshotReference sr")
- .endsWith("select count(m) from maxId m join SnapshotReference sr on sr.snapshot.id = m.snapshotId");
+ .endsWith("select count(*) from maxId m join SnapshotReference sr on sr.snapshot.id = m.snapshotId");
}
@Test // GH-3504
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserExcerptDto.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserExcerptDto.java
new file mode 100644
index 0000000000..af9e522267
--- /dev/null
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserExcerptDto.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jpa.repository.sample;
+
+/**
+ * Hibernate is still a bit picky on records so let's use a class, just in case.
+ *
+ * @author Christoph Strobl
+ */
+public class UserExcerptDto {
+
+ private String firstname;
+ private String lastname;
+
+ public UserExcerptDto(String firstname, String lastname) {
+ this.firstname = firstname;
+ this.lastname = lastname;
+ }
+
+ public String getFirstname() {
+ return firstname;
+ }
+
+ public void setFirstname(String firstname) {
+ this.firstname = firstname;
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public void setLastname(String lastname) {
+ this.lastname = lastname;
+ }
+}
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java
index 1676f886a5..e5b30d0de6 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java
@@ -732,6 +732,25 @@ List findAllAndSortByFunctionResultNamedParameter(@Param("namedParameter
@Query("select u.firstname, u.lastname from User u")
List findMultiselectRecordProjection();
+ /*
+ WITH entities AS (
+ SELECT
+ e.id as id,
+ e.number as number
+ FROM TestEntity e
+ )
+ SELECT new com.example.demo.Result('X', c.id, c.number)
+ FROM entities c
+ """)
+ */
+
+ @Query("""
+ WITH cte_select AS (select u.firstname as firstname, u.lastname as lastname from User u)
+ SELECT new org.springframework.data.jpa.repository.sample.UserExcerptDto(c.firstname, c.lastname)
+ FROM cte_select c
+""")
+ Page findWithCTE(Pageable page);
+
@UserRoleCountProjectingQuery
List dtoProjectionEntityAndAggregatedValue();