Skip to content

Remove 'fetch' part in 'join fetch' clause during generation of count query #2651

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
9 changes: 5 additions & 4 deletions ci/pipeline.properties
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
# Java versions
java.main.tag=17.0.3_7-jdk
java.main.tag=17.0.4.1_1-jdk-focal

# Docker container images - standard
docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.main.tag}

# Supported versions of MongoDB
docker.mongodb.4.4.version=4.4.12
docker.mongodb.5.0.version=5.0.6
docker.mongodb.4.4.version=4.4.17
docker.mongodb.5.0.version=5.0.13
docker.mongodb.6.0.version=6.0.2

# Supported versions of Redis
docker.redis.6.version=6.2.6

# Supported versions of Cassandra
docker.cassandra.3.version=3.11.12
docker.cassandra.3.version=3.11.14

# Docker environment settings
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
<profile>
<id>eclipselink-next</id>
<properties>
<eclipselink>4.0.0-RC2</eclipselink>
<eclipselink>4.0.0</eclipselink>
</properties>
</profile>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.jpa.aot;
package org.springframework.data.jpa.repository.aot;

import java.util.Arrays;

Expand All @@ -24,15 +24,20 @@
import org.springframework.data.jpa.domain.support.AuditingBeanFactoryPostProcessor;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.support.QuerydslJpaPredicateExecutor;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.QuerydslUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

/**
* Runtime hints for JPA AOT processing.
*
* @author Christoph Strobl
* @since 3.0
*/
public class JpaRuntimeHints implements RuntimeHintsRegistrar {
class JpaRuntimeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
Expand All @@ -49,15 +54,23 @@ public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader)
.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS));

hints.reflection().registerTypes(Arrays.asList( //
TypeReference.of(AuditingBeanFactoryPostProcessor.class), //
TypeReference.of(AuditingEntityListener.class)),
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS));
TypeReference.of(AuditingBeanFactoryPostProcessor.class), //
TypeReference.of(AuditingEntityListener.class)),
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS));
}

hints.reflection().registerType(TypeReference.of(SimpleJpaRepository.class),
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS));

// needs to present for evaluating default attribute values in JpaQueryMethod
hints.reflection().registerType(Query.class, hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS));

if (QuerydslUtils.QUERY_DSL_PRESENT) {

hints.reflection().registerType(QuerydslJpaPredicateExecutor.class,
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS)
.onReachableType(QuerydslPredicateExecutor.class));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@
import org.springframework.core.io.ResourceLoader;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.aot.AotRepositoryContext;
import org.springframework.data.aot.RepositoryRegistrationAotProcessor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.DefaultJpaContext;
import org.springframework.data.jpa.repository.support.EntityManagerBeanDefinitionRegistrarPostProcessor;
import org.springframework.data.jpa.repository.support.JpaEvaluationContextExtension;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.aot.AotRepositoryContext;
import org.springframework.data.repository.aot.RepositoryRegistrationAotProcessor;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
import org.springframework.data.repository.config.RepositoryConfigurationSource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public abstract class QueryUtils {
private static final String SIMPLE_COUNT_VALUE = "$2";
private static final String COMPLEX_COUNT_VALUE = "$3 $6";
private static final String COMPLEX_COUNT_LAST_VALUE = "$6";
private static final String FETCH_COMING_AFTER_JOIN_PART = "(?iu)(?<=join)(\\s*fetch\\s*)";
private static final String ORDER_BY_PART = "(?iu)\\s+order\\s+by\\s+.*";

private static final Pattern ALIAS_MATCH;
Expand Down Expand Up @@ -601,6 +602,8 @@ public static String createCountQueryFor(String originalQuery, @Nullable String
countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, countProjection));
}

countQuery = countQuery.replaceAll(FETCH_COMING_AFTER_JOIN_PART, " ");

return countQuery.replaceFirst(ORDER_BY_PART, "");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.data.jpa.aot.JpaRuntimeHints
org.springframework.data.jpa.repository.aot.JpaRuntimeHints
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.jpa.aot;
package org.springframework.data.jpa.repository.aot;

import static org.assertj.core.api.AssertionsForClassTypes.*;
import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection;
import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.*;

import org.junit.jupiter.api.Test;

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect;
import org.springframework.data.jpa.domain.support.AuditingBeanFactoryPostProcessor;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.data.jpa.util.HidingClassLoader;

/**
* Unit tests for {@link JpaRuntimeHints}.
*
* @author Christoph Strobl
*/
class JpaRuntimeHintsUnitTests {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.data.aot.AotRepositoryContext;
import org.springframework.data.repository.aot.AotRepositoryContext;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.javapoet.ClassName;

/**
* @author Christoph Strobl
Expand All @@ -42,7 +43,7 @@ class JpaRepositoryRegistrationAotProcessorUnitTests {
@Test // GH-2628
void aotProcessorMustNotRegisterDomainTypes() {

GenerationContext ctx = new DefaultGenerationContext(new ClassNameGenerator(Object.class),
GenerationContext ctx = new DefaultGenerationContext(new ClassNameGenerator(ClassName.OBJECT),
new InMemoryGeneratedFiles());

new JpaRepositoryConfigExtension.JpaRepositoryRegistrationAotProcessor()
Expand All @@ -59,7 +60,7 @@ public Set<Class<?>> getResolvedTypes() {
@Test // GH-2628
void aotProcessorMustNotRegisterAnnotations() {

GenerationContext ctx = new DefaultGenerationContext(new ClassNameGenerator(Object.class),
GenerationContext ctx = new DefaultGenerationContext(new ClassNameGenerator(ClassName.OBJECT),
new InMemoryGeneratedFiles());

new JpaRepositoryConfigExtension.JpaRepositoryRegistrationAotProcessor()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
* @author Grégoire Druant
* @author Mohammad Hewedy
* @author Greg Turnquist
* @author Vladislav Yukharin
*/
class DefaultQueryUtilsUnitTests {

Expand Down Expand Up @@ -224,6 +225,13 @@ void doesNotPrefixSortsIfFunction() {
.isThrownBy(() -> applySorting("select p from Person p", sort, "p"));
}

@Test // GH-2348
void removesFetchPartInJoinFetchClauseInGeneratedCountQueryIfPresent() {

assertCountQuery("select u from User u left outer join fetch u.roles r left outer JOIN FETCH u.accounts a",
"select count(u) from User u left outer join u.roles r left outer JOIN u.accounts a");
}

@Test // DATAJPA-377
void removesOrderByInGeneratedCountQueryFromOriginalQueryIfPresent() {

Expand Down