Skip to content

Commit 811d2f1

Browse files
committed
Polishing.
Rename Projector to EntityGraphFactory. Remove QuerydslProjector and TypedQueryProjector. Remove MappingContext creation. See #2329 Original pull request: #2345.
1 parent a39cb24 commit 811d2f1

File tree

10 files changed

+134
-249
lines changed

10 files changed

+134
-249
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jpa.repository.support;
17+
18+
import java.util.Set;
19+
20+
import javax.persistence.EntityGraph;
21+
import javax.persistence.EntityManager;
22+
import javax.persistence.Subgraph;
23+
24+
import org.springframework.data.mapping.PropertyPath;
25+
26+
/**
27+
* Factory class to create an {@link EntityGraph} from a collection of property paths.
28+
*
29+
* @author Jens Schauder
30+
* @since 2.6
31+
*/
32+
abstract class EntityGraphFactory {
33+
34+
public static final String HINT = "javax.persistence.fetchgraph";
35+
36+
/**
37+
* Create an {@link EntityGraph} from a collection of properties.
38+
*
39+
* @param domainType
40+
* @param properties
41+
*/
42+
public static <T> EntityGraph<T> create(EntityManager entityManager, Class<T> domainType, Set<String> properties) {
43+
44+
EntityGraph<T> entityGraph = entityManager.createEntityGraph(domainType);
45+
46+
for (String property : properties) {
47+
48+
Subgraph<Object> current = null;
49+
50+
for (PropertyPath path : PropertyPath.from(property, domainType)) {
51+
52+
if (path.hasNext()) {
53+
current = current == null ? entityGraph.addSubgraph(path.getSegment())
54+
: current.addSubgraph(path.getSegment());
55+
continue;
56+
}
57+
58+
if (current == null) {
59+
entityGraph.addAttributeNodes(path.getSegment());
60+
} else {
61+
current.addAttributeNodes(path.getSegment());
62+
63+
}
64+
}
65+
}
66+
67+
return entityGraph;
68+
}
69+
70+
}

src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByExample.java

+20-28
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@
3232
import org.springframework.data.domain.Pageable;
3333
import org.springframework.data.domain.Sort;
3434
import org.springframework.data.jpa.repository.query.EscapeCharacter;
35-
import org.springframework.data.mapping.PersistentEntity;
36-
import org.springframework.data.mapping.PersistentProperty;
37-
import org.springframework.data.mapping.context.MappingContext;
3835
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
3936
import org.springframework.data.support.PageableExecutionUtils;
4037
import org.springframework.util.Assert;
@@ -58,34 +55,29 @@ class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<S, R> imple
5855
private final Function<Example<S>, Boolean> existsOperation;
5956
private final EntityManager entityManager;
6057
private final EscapeCharacter escapeCharacter;
61-
private final Projector<TypedQuery<?>> projector;
6258

6359
public FetchableFluentQueryByExample(Example<S> example, Function<Sort, TypedQuery<S>> finder,
6460
Function<Example<S>, Long> countOperation, Function<Example<S>, Boolean> existsOperation,
65-
MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> context,
6661
EntityManager entityManager, EscapeCharacter escapeCharacter) {
6762
this(example, example.getProbeType(), (Class<R>) example.getProbeType(), Sort.unsorted(), Collections.emptySet(),
68-
finder, countOperation, existsOperation, context, entityManager, escapeCharacter,
69-
new TypedQueryProjector(entityManager));
63+
finder, countOperation, existsOperation, entityManager, escapeCharacter);
7064
}
7165

7266
private FetchableFluentQueryByExample(Example<S> example, Class<S> entityType, Class<R> returnType, Sort sort,
7367
Collection<String> properties, Function<Sort, TypedQuery<S>> finder, Function<Example<S>, Long> countOperation,
7468
Function<Example<S>, Boolean> existsOperation,
75-
MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> context,
76-
EntityManager entityManager, EscapeCharacter escapeCharacter, Projector<TypedQuery<?>> projector) {
69+
EntityManager entityManager, EscapeCharacter escapeCharacter) {
7770

78-
super(returnType, sort, properties, context, entityType);
71+
super(returnType, sort, properties, entityType);
7972
this.example = example;
8073
this.finder = finder;
8174
this.countOperation = countOperation;
8275
this.existsOperation = existsOperation;
8376
this.entityManager = entityManager;
8477
this.escapeCharacter = escapeCharacter;
85-
this.projector = projector;
8678
}
8779

88-
/*
80+
/*
8981
* (non-Javadoc)
9082
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#sortBy(org.springframework.data.domain.Sort)
9183
*/
@@ -95,11 +87,10 @@ public FetchableFluentQuery<R> sortBy(Sort sort) {
9587
Assert.notNull(sort, "Sort must not be null!");
9688

9789
return new FetchableFluentQueryByExample<>(example, entityType, resultType, sort.and(sort), properties, finder,
98-
countOperation, existsOperation, context, entityManager, escapeCharacter,
99-
new TypedQueryProjector(entityManager));
90+
countOperation, existsOperation, entityManager, escapeCharacter);
10091
}
10192

102-
/*
93+
/*
10394
* (non-Javadoc)
10495
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#as(java.lang.Class)
10596
*/
@@ -112,23 +103,21 @@ public <NR> FetchableFluentQuery<NR> as(Class<NR> resultType) {
112103
}
113104

114105
return new FetchableFluentQueryByExample<>(example, entityType, resultType, sort, properties, finder,
115-
countOperation, existsOperation, context, entityManager, escapeCharacter,
116-
new TypedQueryProjector(entityManager));
106+
countOperation, existsOperation, entityManager, escapeCharacter);
117107
}
118108

119-
/*
109+
/*
120110
* (non-Javadoc)
121111
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#project(java.util.Collection)
122112
*/
123113
@Override
124114
public FetchableFluentQuery<R> project(Collection<String> properties) {
125115

126116
return new FetchableFluentQueryByExample<>(example, entityType, resultType, sort, mergeProperties(properties),
127-
finder, countOperation, existsOperation, context, entityManager, escapeCharacter,
128-
new TypedQueryProjector(entityManager));
117+
finder, countOperation, existsOperation, entityManager, escapeCharacter);
129118
}
130119

131-
/*
120+
/*
132121
* (non-Javadoc)
133122
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#oneValue()
134123
*/
@@ -147,7 +136,7 @@ public R oneValue() {
147136
return results.isEmpty() ? null : getConversionFunction().apply(results.get(0));
148137
}
149138

150-
/*
139+
/*
151140
* (non-Javadoc)
152141
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#firstValue()
153142
*/
@@ -162,7 +151,7 @@ public R firstValue() {
162151
return results.isEmpty() ? null : getConversionFunction().apply(results.get(0));
163152
}
164153

165-
/*
154+
/*
166155
* (non-Javadoc)
167156
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#all()
168157
*/
@@ -174,7 +163,7 @@ public List<R> all() {
174163
return convert(resultList);
175164
}
176165

177-
/*
166+
/*
178167
* (non-Javadoc)
179168
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#page(org.springframework.data.domain.Pageable)
180169
*/
@@ -183,7 +172,7 @@ public Page<R> page(Pageable pageable) {
183172
return pageable.isUnpaged() ? new PageImpl<>(all()) : readPage(pageable);
184173
}
185174

186-
/*
175+
/*
187176
* (non-Javadoc)
188177
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#stream()
189178
*/
@@ -195,7 +184,7 @@ public Stream<R> stream() {
195184
.map(getConversionFunction());
196185
}
197186

198-
/*
187+
/*
199188
* (non-Javadoc)
200189
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#count()
201190
*/
@@ -204,7 +193,7 @@ public long count() {
204193
return countOperation.apply(example);
205194
}
206195

207-
/*
196+
/*
208197
* (non-Javadoc)
209198
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#exists()
210199
*/
@@ -230,7 +219,10 @@ private Page<R> readPage(Pageable pageable) {
230219
private TypedQuery<S> createSortedAndProjectedQuery() {
231220

232221
TypedQuery<S> query = finder.apply(sort);
233-
projector.apply(entityType, query, properties);
222+
223+
if (!properties.isEmpty()) {
224+
query.setHint(EntityGraphFactory.HINT, EntityGraphFactory.create(entityManager, entityType, properties));
225+
}
234226

235227
return query;
236228
}

src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByPredicate.java

+27-26
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,13 @@
2323
import java.util.function.Function;
2424
import java.util.stream.Stream;
2525

26+
import javax.persistence.EntityManager;
27+
2628
import org.springframework.dao.IncorrectResultSizeDataAccessException;
2729
import org.springframework.data.domain.Page;
2830
import org.springframework.data.domain.PageImpl;
2931
import org.springframework.data.domain.Pageable;
3032
import org.springframework.data.domain.Sort;
31-
import org.springframework.data.mapping.PersistentEntity;
32-
import org.springframework.data.mapping.PersistentProperty;
33-
import org.springframework.data.mapping.context.MappingContext;
3433
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
3534
import org.springframework.data.support.PageableExecutionUtils;
3635
import org.springframework.util.Assert;
@@ -56,34 +55,32 @@ class FetchableFluentQueryByPredicate<S, R> extends FluentQuerySupport<S, R> imp
5655
private final BiFunction<Sort, Pageable, AbstractJPAQuery<?, ?>> pagedFinder;
5756
private final Function<Predicate, Long> countOperation;
5857
private final Function<Predicate, Boolean> existsOperation;
59-
private final Projector<AbstractJPAQuery<?, ?>> projector;
58+
private final EntityManager entityManager;
6059

6160
public FetchableFluentQueryByPredicate(Predicate predicate, Class<S> entityType,
6261
Function<Sort, AbstractJPAQuery<?, ?>> finder, BiFunction<Sort, Pageable, AbstractJPAQuery<?, ?>> pagedFinder,
6362
Function<Predicate, Long> countOperation, Function<Predicate, Boolean> existsOperation,
64-
MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> context,
65-
Projector<AbstractJPAQuery<?, ?>> projector) {
63+
EntityManager entityManager) {
6664
this(predicate, entityType, (Class<R>) entityType, Sort.unsorted(), Collections.emptySet(), finder, pagedFinder,
67-
countOperation, existsOperation, context, projector);
65+
countOperation, existsOperation, entityManager);
6866
}
6967

7068
private FetchableFluentQueryByPredicate(Predicate predicate, Class<S> entityType, Class<R> resultType, Sort sort,
7169
Collection<String> properties, Function<Sort, AbstractJPAQuery<?, ?>> finder,
7270
BiFunction<Sort, Pageable, AbstractJPAQuery<?, ?>> pagedFinder, Function<Predicate, Long> countOperation,
7371
Function<Predicate, Boolean> existsOperation,
74-
MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> context,
75-
Projector<AbstractJPAQuery<?, ?>> projector) {
72+
EntityManager entityManager) {
7673

77-
super(resultType, sort, properties, context, entityType);
74+
super(resultType, sort, properties, entityType);
7875
this.predicate = predicate;
7976
this.finder = finder;
8077
this.pagedFinder = pagedFinder;
8178
this.countOperation = countOperation;
8279
this.existsOperation = existsOperation;
83-
this.projector = projector;
80+
this.entityManager = entityManager;
8481
}
8582

86-
/*
83+
/*
8784
* (non-Javadoc)
8885
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#sortBy(org.springframework.data.domain.Sort)
8986
*/
@@ -93,10 +90,10 @@ public FetchableFluentQuery<R> sortBy(Sort sort) {
9390
Assert.notNull(sort, "Sort must not be null!");
9491

9592
return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort.and(sort), properties, finder,
96-
pagedFinder, countOperation, existsOperation, context, projector);
93+
pagedFinder, countOperation, existsOperation, entityManager);
9794
}
9895

99-
/*
96+
/*
10097
* (non-Javadoc)
10198
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#as(java.lang.Class)
10299
*/
@@ -110,21 +107,21 @@ public <NR> FetchableFluentQuery<NR> as(Class<NR> resultType) {
110107
}
111108

112109
return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort, properties, finder,
113-
pagedFinder, countOperation, existsOperation, context, projector);
110+
pagedFinder, countOperation, existsOperation, entityManager);
114111
}
115112

116-
/*
113+
/*
117114
* (non-Javadoc)
118115
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#project(java.util.Collection)
119116
*/
120117
@Override
121118
public FetchableFluentQuery<R> project(Collection<String> properties) {
122119

123120
return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort, mergeProperties(properties),
124-
finder, pagedFinder, countOperation, existsOperation, context, projector);
121+
finder, pagedFinder, countOperation, existsOperation, entityManager);
125122
}
126123

127-
/*
124+
/*
128125
* (non-Javadoc)
129126
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#oneValue()
130127
*/
@@ -142,7 +139,7 @@ public R oneValue() {
142139
return results.isEmpty() ? null : getConversionFunction().apply(results.get(0));
143140
}
144141

145-
/*
142+
/*
146143
* (non-Javadoc)
147144
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#firstValue()
148145
*/
@@ -156,7 +153,7 @@ public R firstValue() {
156153
return results.isEmpty() ? null : getConversionFunction().apply(results.get(0));
157154
}
158155

159-
/*
156+
/*
160157
* (non-Javadoc)
161158
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#all()
162159
*/
@@ -165,7 +162,7 @@ public List<R> all() {
165162
return convert(createSortedAndProjectedQuery().fetch());
166163
}
167164

168-
/*
165+
/*
169166
* (non-Javadoc)
170167
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#page(org.springframework.data.domain.Pageable)
171168
*/
@@ -174,7 +171,7 @@ public Page<R> page(Pageable pageable) {
174171
return pageable.isUnpaged() ? new PageImpl<>(all()) : readPage(pageable);
175172
}
176173

177-
/*
174+
/*
178175
* (non-Javadoc)
179176
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#stream()
180177
*/
@@ -186,7 +183,7 @@ public Stream<R> stream() {
186183
.map(getConversionFunction());
187184
}
188185

189-
/*
186+
/*
190187
* (non-Javadoc)
191188
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#count()
192189
*/
@@ -195,7 +192,7 @@ public long count() {
195192
return countOperation.apply(predicate);
196193
}
197194

198-
/*
195+
/*
199196
* (non-Javadoc)
200197
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#exists()
201198
*/
@@ -206,8 +203,12 @@ public boolean exists() {
206203

207204
private AbstractJPAQuery<?, ?> createSortedAndProjectedQuery() {
208205

209-
final AbstractJPAQuery<?, ?> query = finder.apply(sort);
210-
projector.apply(entityType, query, properties);
206+
AbstractJPAQuery<?, ?> query = finder.apply(sort);
207+
208+
if (!properties.isEmpty()) {
209+
query.setHint(EntityGraphFactory.HINT, EntityGraphFactory.create(entityManager, entityType, properties));
210+
}
211+
211212
return query;
212213
}
213214

0 commit comments

Comments
 (0)