From d637ce35df37eb9c47cdfe9e0e99f2728a5c41f1 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 29 Oct 2021 12:01:17 +0200 Subject: [PATCH] Polishing. Rename Projector to EntityGraphFactory. Remove QuerydslProjector and TypedQueryProjector. Remove MappingContext creation. See #2329 Original pull request: #2345. --- .../support/EntityGraphFactory.java | 70 ++++++++++++++++++ .../FetchableFluentQueryByExample.java | 48 ++++++------- .../FetchableFluentQueryByPredicate.java | 53 +++++++------- .../support/FluentQuerySupport.java | 11 +-- .../jpa/repository/support/Projector.java | 72 ------------------- .../support/QuerydslJpaPredicateExecutor.java | 9 +-- .../repository/support/QuerydslProjector.java | 39 ---------- .../support/SimpleJpaRepository.java | 10 +-- .../support/TypedQueryProjector.java | 37 ---------- ....java => EntityGraphFactoryUnitTests.java} | 34 +++------ 10 files changed, 134 insertions(+), 249 deletions(-) create mode 100644 src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java delete mode 100644 src/main/java/org/springframework/data/jpa/repository/support/Projector.java delete mode 100644 src/main/java/org/springframework/data/jpa/repository/support/QuerydslProjector.java delete mode 100644 src/main/java/org/springframework/data/jpa/repository/support/TypedQueryProjector.java rename src/test/java/org/springframework/data/jpa/repository/support/{QuerydslProjectorUnitTests.java => EntityGraphFactoryUnitTests.java} (63%) diff --git a/src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java b/src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java new file mode 100644 index 000000000..a619916bf --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021 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.support; + +import java.util.Set; + +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.Subgraph; + +import org.springframework.data.mapping.PropertyPath; + +/** + * Factory class to create an {@link EntityGraph} from a collection of property paths. + * + * @author Jens Schauder + * @since 2.6 + */ +abstract class EntityGraphFactory { + + public static final String HINT = "javax.persistence.fetchgraph"; + + /** + * Create an {@link EntityGraph} from a collection of properties. + * + * @param domainType + * @param properties + */ + public static EntityGraph create(EntityManager entityManager, Class domainType, Set properties) { + + EntityGraph entityGraph = entityManager.createEntityGraph(domainType); + + for (String property : properties) { + + Subgraph current = null; + + for (PropertyPath path : PropertyPath.from(property, domainType)) { + + if (path.hasNext()) { + current = current == null ? entityGraph.addSubgraph(path.getSegment()) + : current.addSubgraph(path.getSegment()); + continue; + } + + if (current == null) { + entityGraph.addAttributeNodes(path.getSegment()); + } else { + current.addAttributeNodes(path.getSegment()); + + } + } + } + + return entityGraph; + } + +} diff --git a/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByExample.java b/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByExample.java index 7e395ca15..cb2645bfc 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByExample.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByExample.java @@ -32,9 +32,6 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.query.EscapeCharacter; -import org.springframework.data.mapping.PersistentEntity; -import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery; import org.springframework.data.support.PageableExecutionUtils; import org.springframework.util.Assert; @@ -58,34 +55,29 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple private final Function, Boolean> existsOperation; private final EntityManager entityManager; private final EscapeCharacter escapeCharacter; - private final Projector> projector; public FetchableFluentQueryByExample(Example example, Function> finder, Function, Long> countOperation, Function, Boolean> existsOperation, - MappingContext, ? extends PersistentProperty> context, EntityManager entityManager, EscapeCharacter escapeCharacter) { this(example, example.getProbeType(), (Class) example.getProbeType(), Sort.unsorted(), Collections.emptySet(), - finder, countOperation, existsOperation, context, entityManager, escapeCharacter, - new TypedQueryProjector(entityManager)); + finder, countOperation, existsOperation, entityManager, escapeCharacter); } private FetchableFluentQueryByExample(Example example, Class entityType, Class returnType, Sort sort, Collection properties, Function> finder, Function, Long> countOperation, Function, Boolean> existsOperation, - MappingContext, ? extends PersistentProperty> context, - EntityManager entityManager, EscapeCharacter escapeCharacter, Projector> projector) { + EntityManager entityManager, EscapeCharacter escapeCharacter) { - super(returnType, sort, properties, context, entityType); + super(returnType, sort, properties, entityType); this.example = example; this.finder = finder; this.countOperation = countOperation; this.existsOperation = existsOperation; this.entityManager = entityManager; this.escapeCharacter = escapeCharacter; - this.projector = projector; } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#sortBy(org.springframework.data.domain.Sort) */ @@ -95,11 +87,10 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple Assert.notNull(sort, "Sort must not be null!"); return new FetchableFluentQueryByExample<>(example, entityType, resultType, sort.and(sort), properties, finder, - countOperation, existsOperation, context, entityManager, escapeCharacter, - new TypedQueryProjector(entityManager)); + countOperation, existsOperation, entityManager, escapeCharacter); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#as(java.lang.Class) */ @@ -112,11 +103,10 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple } return new FetchableFluentQueryByExample<>(example, entityType, resultType, sort, properties, finder, - countOperation, existsOperation, context, entityManager, escapeCharacter, - new TypedQueryProjector(entityManager)); + countOperation, existsOperation, entityManager, escapeCharacter); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#project(java.util.Collection) */ @@ -124,11 +114,10 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple public FetchableFluentQuery project(Collection properties) { return new FetchableFluentQueryByExample<>(example, entityType, resultType, sort, mergeProperties(properties), - finder, countOperation, existsOperation, context, entityManager, escapeCharacter, - new TypedQueryProjector(entityManager)); + finder, countOperation, existsOperation, entityManager, escapeCharacter); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#oneValue() */ @@ -147,7 +136,7 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple return results.isEmpty() ? null : getConversionFunction().apply(results.get(0)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#firstValue() */ @@ -162,7 +151,7 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple return results.isEmpty() ? null : getConversionFunction().apply(results.get(0)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#all() */ @@ -174,7 +163,7 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple return convert(resultList); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#page(org.springframework.data.domain.Pageable) */ @@ -183,7 +172,7 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple return pageable.isUnpaged() ? new PageImpl<>(all()) : readPage(pageable); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#stream() */ @@ -195,7 +184,7 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple .map(getConversionFunction()); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#count() */ @@ -204,7 +193,7 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple return countOperation.apply(example); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#exists() */ @@ -230,7 +219,10 @@ class FetchableFluentQueryByExample extends FluentQuerySupport imple private TypedQuery createSortedAndProjectedQuery() { TypedQuery query = finder.apply(sort); - projector.apply(entityType, query, properties); + + if (!properties.isEmpty()) { + query.setHint(EntityGraphFactory.HINT, EntityGraphFactory.create(entityManager, entityType, properties)); + } return query; } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByPredicate.java b/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByPredicate.java index ff9c67f83..f71eeacc0 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByPredicate.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByPredicate.java @@ -23,14 +23,13 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Stream; +import javax.persistence.EntityManager; + import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.data.mapping.PersistentEntity; -import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery; import org.springframework.data.support.PageableExecutionUtils; import org.springframework.util.Assert; @@ -56,34 +55,32 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp private final BiFunction> pagedFinder; private final Function countOperation; private final Function existsOperation; - private final Projector> projector; + private final EntityManager entityManager; public FetchableFluentQueryByPredicate(Predicate predicate, Class entityType, Function> finder, BiFunction> pagedFinder, Function countOperation, Function existsOperation, - MappingContext, ? extends PersistentProperty> context, - Projector> projector) { + EntityManager entityManager) { this(predicate, entityType, (Class) entityType, Sort.unsorted(), Collections.emptySet(), finder, pagedFinder, - countOperation, existsOperation, context, projector); + countOperation, existsOperation, entityManager); } private FetchableFluentQueryByPredicate(Predicate predicate, Class entityType, Class resultType, Sort sort, Collection properties, Function> finder, BiFunction> pagedFinder, Function countOperation, Function existsOperation, - MappingContext, ? extends PersistentProperty> context, - Projector> projector) { + EntityManager entityManager) { - super(resultType, sort, properties, context, entityType); + super(resultType, sort, properties, entityType); this.predicate = predicate; this.finder = finder; this.pagedFinder = pagedFinder; this.countOperation = countOperation; this.existsOperation = existsOperation; - this.projector = projector; + this.entityManager = entityManager; } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#sortBy(org.springframework.data.domain.Sort) */ @@ -93,10 +90,10 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp Assert.notNull(sort, "Sort must not be null!"); return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort.and(sort), properties, finder, - pagedFinder, countOperation, existsOperation, context, projector); + pagedFinder, countOperation, existsOperation, entityManager); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#as(java.lang.Class) */ @@ -110,10 +107,10 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp } return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort, properties, finder, - pagedFinder, countOperation, existsOperation, context, projector); + pagedFinder, countOperation, existsOperation, entityManager); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#project(java.util.Collection) */ @@ -121,10 +118,10 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp public FetchableFluentQuery project(Collection properties) { return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort, mergeProperties(properties), - finder, pagedFinder, countOperation, existsOperation, context, projector); + finder, pagedFinder, countOperation, existsOperation, entityManager); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#oneValue() */ @@ -142,7 +139,7 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp return results.isEmpty() ? null : getConversionFunction().apply(results.get(0)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#firstValue() */ @@ -156,7 +153,7 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp return results.isEmpty() ? null : getConversionFunction().apply(results.get(0)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#all() */ @@ -165,7 +162,7 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp return convert(createSortedAndProjectedQuery().fetch()); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#page(org.springframework.data.domain.Pageable) */ @@ -174,7 +171,7 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp return pageable.isUnpaged() ? new PageImpl<>(all()) : readPage(pageable); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#stream() */ @@ -186,7 +183,7 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp .map(getConversionFunction()); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#count() */ @@ -195,7 +192,7 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp return countOperation.apply(predicate); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#exists() */ @@ -206,8 +203,12 @@ class FetchableFluentQueryByPredicate extends FluentQuerySupport imp private AbstractJPAQuery createSortedAndProjectedQuery() { - final AbstractJPAQuery query = finder.apply(sort); - projector.apply(entityType, query, properties); + AbstractJPAQuery query = finder.apply(sort); + + if (!properties.isEmpty()) { + query.setHint(EntityGraphFactory.HINT, EntityGraphFactory.create(entityManager, entityType, properties)); + } + return query; } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/FluentQuerySupport.java b/src/main/java/org/springframework/data/jpa/repository/support/FluentQuerySupport.java index 2f299cc9c..ab7d58ddc 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/FluentQuerySupport.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/FluentQuerySupport.java @@ -23,9 +23,6 @@ import java.util.function.Function; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.domain.Sort; -import org.springframework.data.mapping.PersistentEntity; -import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.lang.Nullable; @@ -41,15 +38,12 @@ abstract class FluentQuerySupport { protected final Class resultType; protected final Sort sort; - /** Properties on which the query projects. {@literal null} stands for no special projection. */ protected final Set properties; - protected final MappingContext, ? extends PersistentProperty> context; protected final Class entityType; private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory(); - FluentQuerySupport(Class resultType, Sort sort, @Nullable Collection properties, - MappingContext, ? extends PersistentProperty> context, Class entityType) { + FluentQuerySupport(Class resultType, Sort sort, @Nullable Collection properties, Class entityType) { this.resultType = resultType; this.sort = sort; @@ -57,10 +51,9 @@ abstract class FluentQuerySupport { if (properties != null) { this.properties = new HashSet<>(properties); } else { - this.properties = new HashSet<>(); + this.properties = Collections.emptySet(); } - this.context = context; this.entityType = entityType; } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/Projector.java b/src/main/java/org/springframework/data/jpa/repository/support/Projector.java deleted file mode 100644 index 482d5f01c..000000000 --- a/src/main/java/org/springframework/data/jpa/repository/support/Projector.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2021 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.support; - -import java.util.Set; - -import javax.persistence.EntityGraph; -import javax.persistence.EntityManager; -import javax.persistence.Subgraph; - -import org.springframework.data.mapping.PropertyPath; - -/** - * Turns a collection of property paths to an {@link EntityGraph} and applies it to a query abstraction - * - * @param the type of the query abstraction. - * @author Jens Schauder - * @since 2.6 - */ -abstract class Projector { - - private final EntityManager entityManager; - - protected Projector(EntityManager entityManager) { - this.entityManager = entityManager; - } - - public void apply(Class domainType, Q query, Set properties) { - - if (!properties.isEmpty()) { - - final javax.persistence.EntityGraph entityGraph = entityManager.createEntityGraph(domainType); - - for (String property : properties) { - - Subgraph subgraph = null; - - for (PropertyPath path : PropertyPath.from(property, domainType)) { - - if (path.hasNext()) { - subgraph = subgraph == null ? entityGraph.addSubgraph(path.getSegment()) - : subgraph.addSubgraph(path.getSegment()); - } else { - - if (subgraph == null) { - entityGraph.addAttributeNodes(path.getSegment()); - } else { - subgraph.addAttributeNodes(path.getSegment()); - } - } - } - } - - applyEntityGraph(query, entityGraph); - } - } - - abstract void applyEntityGraph(Q query, EntityGraph entityGraph); -} diff --git a/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutor.java b/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutor.java index 80ac35111..d748761dd 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutor.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutor.java @@ -15,7 +15,6 @@ */ package org.springframework.data.jpa.repository.support; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.BiFunction; @@ -28,7 +27,6 @@ import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.querydsl.EntityPathResolver; import org.springframework.data.querydsl.QSort; @@ -69,7 +67,7 @@ public class QuerydslJpaPredicateExecutor implements QuerydslPredicateExecuto /** * Creates a new {@link QuerydslJpaPredicateExecutor} from the given domain class and {@link EntityManager} and uses * the given {@link EntityPathResolver} to translate the domain class into an {@link EntityPath}. - * + * * @param entityInformation must not be {@literal null}. * @param entityManager must not be {@literal null}. * @param resolver must not be {@literal null}. @@ -167,7 +165,7 @@ public class QuerydslJpaPredicateExecutor implements QuerydslPredicateExecuto return PageableExecutionUtils.getPage(query.fetch(), pageable, countQuery::fetchCount); } - /* + /* * (non-Javadoc) * @see org.springframework.data.querydsl.QuerydslPredicateExecutor#findBy(com.querydsl.core.types.Predicate, java.util.function.Function) */ @@ -206,8 +204,7 @@ public class QuerydslJpaPredicateExecutor implements QuerydslPredicateExecuto pagedFinder, // this::count, // this::exists, // - new JpaMetamodelMappingContext(Collections.singleton(this.entityManager.getMetamodel())), // - new QuerydslProjector(entityManager) // + entityManager // ); return queryFunction.apply((FetchableFluentQuery) fluentQuery); diff --git a/src/main/java/org/springframework/data/jpa/repository/support/QuerydslProjector.java b/src/main/java/org/springframework/data/jpa/repository/support/QuerydslProjector.java deleted file mode 100644 index 22bd98bed..000000000 --- a/src/main/java/org/springframework/data/jpa/repository/support/QuerydslProjector.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2021 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.support; - -import javax.persistence.EntityGraph; -import javax.persistence.EntityManager; - -import com.querydsl.jpa.impl.AbstractJPAQuery; - -/** - * Applies fetchgraph hints to {@code AbstractJPAQuery}. - * - * @author Jens Schauder - * @since 2.6 - */ -class QuerydslProjector extends Projector> { - - QuerydslProjector(EntityManager entityManager) { - super(entityManager); - } - - @Override - void applyEntityGraph(AbstractJPAQuery query, EntityGraph entityGraph) { - query.setHint("javax.persistence.fetchgraph", entityGraph); - } -} diff --git a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java index b69d43667..f5f2fe1ef 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java @@ -48,15 +48,11 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.convert.QueryByExamplePredicateBuilder; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; import org.springframework.data.jpa.provider.PersistenceProvider; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.query.EscapeCharacter; import org.springframework.data.jpa.repository.query.QueryUtils; import org.springframework.data.jpa.repository.support.QueryHints.NoHints; -import org.springframework.data.mapping.PersistentEntity; -import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery; import org.springframework.data.support.PageableExecutionUtils; import org.springframework.data.util.ProxyUtils; @@ -94,7 +90,6 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation entityInformation; private final EntityManager em; private final PersistenceProvider provider; - private final MappingContext, ? extends PersistentProperty> context; private @Nullable CrudMethodMetadata metadata; private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT; @@ -113,9 +108,6 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation implements JpaRepositoryImplementation fluentQuery = new FetchableFluentQueryByExample<>(example, finder, this::count, - this::exists, this.context, this.em, this.escapeCharacter); + this::exists, this.em, this.escapeCharacter); return queryFunction.apply(fluentQuery); } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/TypedQueryProjector.java b/src/main/java/org/springframework/data/jpa/repository/support/TypedQueryProjector.java deleted file mode 100644 index d3b15e5cf..000000000 --- a/src/main/java/org/springframework/data/jpa/repository/support/TypedQueryProjector.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2021 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.support; - -import javax.persistence.EntityGraph; -import javax.persistence.EntityManager; -import javax.persistence.TypedQuery; - -/** - * Applies fetchgraph hints to {@code TypedQuery}. - * - * @author Jens Schauder - * @since 2.6 - */ -public class TypedQueryProjector extends Projector> { - - public TypedQueryProjector(EntityManager entityManager) { - super(entityManager); - } - - void applyEntityGraph(TypedQuery query, EntityGraph entityGraph) { - query.setHint("javax.persistence.fetchgraph", entityGraph); - } -} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/QuerydslProjectorUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/EntityGraphFactoryUnitTests.java similarity index 63% rename from src/test/java/org/springframework/data/jpa/repository/support/QuerydslProjectorUnitTests.java rename to src/test/java/org/springframework/data/jpa/repository/support/EntityGraphFactoryUnitTests.java index cac7e9200..e0ac1ce52 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/QuerydslProjectorUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/EntityGraphFactoryUnitTests.java @@ -16,7 +16,6 @@ package org.springframework.data.jpa.repository.support; import static java.util.Arrays.*; -import static java.util.Collections.*; import static org.mockito.Mockito.*; import java.util.HashSet; @@ -28,18 +27,16 @@ import javax.persistence.Subgraph; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.querydsl.jpa.impl.AbstractJPAQuery; - /** - * Unit tests for {@link QuerydslProjector}. + * Unit tests for {@link EntityGraphFactory}. * * @author Jens Schauder */ -public class QuerydslProjectorUnitTests { +@SuppressWarnings("rawtypes") +class EntityGraphFactoryUnitTests { EntityManager em = mock(EntityManager.class); - private EntityGraph entityGraph; - private AbstractJPAQuery jpaQuery = mock(AbstractJPAQuery.class); + EntityGraph entityGraph; @BeforeEach void beforeEach() { @@ -48,21 +45,14 @@ public class QuerydslProjectorUnitTests { when(em.createEntityGraph(DummyEntity.class)).thenReturn(entityGraph); } - // GH-2329 - @Test - void emptySetOfPropertiesDoesNotCreateEntityGraph() { - new QuerydslProjector(em).apply(DummyEntity.class, jpaQuery, emptySet()); - } - // GH-2329 @Test void simpleSetOfPropertiesGetRegistered() { - final HashSet properties = new HashSet<>(asList("one", "two")); + HashSet properties = new HashSet<>(asList("one", "two")); - new QuerydslProjector(em).apply(DummyEntity.class, jpaQuery, properties); + entityGraph = EntityGraphFactory.create(em, DummyEntity.class, properties); - verify(jpaQuery).setHint("javax.persistence.fetchgraph", entityGraph); verify(entityGraph).addAttributeNodes("one"); verify(entityGraph).addAttributeNodes("two"); } @@ -71,20 +61,18 @@ public class QuerydslProjectorUnitTests { @Test void setOfCompositePropertiesGetRegisteredPiecewise() { - final HashSet properties = new HashSet<>(asList("one.two", "eins.zwei.drei")); + HashSet properties = new HashSet<>(asList("one.two", "eins.zwei.drei")); - new QuerydslProjector(em).apply(DummyEntity.class, jpaQuery, properties); - - verify(jpaQuery).setHint("javax.persistence.fetchgraph", entityGraph); + entityGraph = EntityGraphFactory.create(em, DummyEntity.class, properties); verify(entityGraph).addSubgraph("one"); - Subgraph one = entityGraph.addSubgraph("one"); + Subgraph one = entityGraph.addSubgraph("one"); verify(one).addAttributeNodes("two"); verify(entityGraph).addSubgraph("eins"); - Subgraph eins = entityGraph.addSubgraph("eins"); + Subgraph eins = entityGraph.addSubgraph("eins"); verify(eins).addSubgraph("zwei"); - Subgraph zwei = eins.addSubgraph("zwei"); + Subgraph zwei = eins.addSubgraph("zwei"); verify(zwei).addAttributeNodes("drei"); }