Skip to content

Commit 08faa52

Browse files
committed
DATAMONGO-1108 - Performance improvements in BasicMongoPersistentEntity.
BasicMongoPersistentEntity.getCollection() now avoids repeated SpEL-parsing and evaluating in case no SpEL expression is used. Parsing is happening at most once now. Evaluation is skipped entirely if the configured collection String is not or does not contain an expression.
1 parent 33bc4ff commit 08faa52

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java

+41-11
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.springframework.data.util.TypeInformation;
3636
import org.springframework.expression.Expression;
3737
import org.springframework.expression.ParserContext;
38+
import org.springframework.expression.common.LiteralExpression;
3839
import org.springframework.expression.spel.standard.SpelExpressionParser;
3940
import org.springframework.expression.spel.support.StandardEvaluationContext;
4041
import org.springframework.util.Assert;
@@ -54,31 +55,36 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
5455
MongoPersistentEntity<T>, ApplicationContextAware {
5556

5657
private static final String AMBIGUOUS_FIELD_MAPPING = "Ambiguous field mapping detected! Both %s and %s map to the same field name %s! Disambiguate using @Field annotation!";
58+
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
59+
5760
private final String collection;
5861
private final String language;
59-
private final SpelExpressionParser parser;
62+
6063
private final StandardEvaluationContext context;
64+
private final Expression expression;
6165

6266
/**
6367
* Creates a new {@link BasicMongoPersistentEntity} with the given {@link TypeInformation}. Will default the
6468
* collection name to the entities simple type name.
6569
*
66-
* @param typeInformation
70+
* @param typeInformation must not be {@literal null}.
6771
*/
6872
public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {
6973

7074
super(typeInformation, MongoPersistentPropertyComparator.INSTANCE);
7175

72-
this.parser = new SpelExpressionParser();
73-
this.context = new StandardEvaluationContext();
74-
7576
Class<?> rawType = typeInformation.getType();
7677
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
7778

78-
if (rawType.isAnnotationPresent(Document.class)) {
79-
Document d = rawType.getAnnotation(Document.class);
80-
this.collection = StringUtils.hasText(d.collection()) ? d.collection() : fallback;
81-
this.language = StringUtils.hasText(d.language()) ? d.language() : "";
79+
Document document = rawType.getAnnotation(Document.class);
80+
81+
this.expression = detectExpression(document);
82+
this.context = new StandardEvaluationContext();
83+
84+
if (document != null) {
85+
86+
this.collection = StringUtils.hasText(document.collection()) ? document.collection() : fallback;
87+
this.language = StringUtils.hasText(document.language()) ? document.language() : "";
8288
} else {
8389
this.collection = fallback;
8490
this.language = "";
@@ -101,8 +107,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
101107
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getCollection()
102108
*/
103109
public String getCollection() {
104-
Expression expression = parser.parseExpression(collection, ParserContext.TEMPLATE_EXPRESSION);
105-
return expression.getValue(context, String.class);
110+
return expression == null ? collection : expression.getValue(context, String.class);
106111
}
107112

108113
/*
@@ -236,6 +241,31 @@ protected MongoPersistentProperty returnPropertyIfBetterIdPropertyCandidateOrNul
236241
return null;
237242
}
238243

244+
/**
245+
* Returns a SpEL {@link Expression} frór the collection String expressed in the given {@link Document} annotation if
246+
* present or {@literal null} otherwise. Will also return {@literal null} it the collection {@link String} evaluates
247+
* to a {@link LiteralExpression} (indicating that no subsequent evaluation is necessary).
248+
*
249+
* @param document can be {@literal null}
250+
* @return
251+
*/
252+
private static Expression detectExpression(Document document) {
253+
254+
if (document == null) {
255+
return null;
256+
}
257+
258+
String collection = document.collection();
259+
260+
if (!StringUtils.hasText(collection)) {
261+
return null;
262+
}
263+
264+
Expression expression = PARSER.parseExpression(document.collection(), ParserContext.TEMPLATE_EXPRESSION);
265+
266+
return expression instanceof LiteralExpression ? null : expression;
267+
}
268+
239269
/**
240270
* Handler to collect {@link MongoPersistentProperty} instances and check that each of them is mapped to a distinct
241271
* field name.

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java

+6
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public void evaluatesSpELExpression() {
5555
assertThat(entity.getCollection(), is("35"));
5656
}
5757

58+
/**
59+
* @see DATAMONGO-65, DATAMONGO-1108
60+
*/
5861
@Test
5962
public void collectionAllowsReferencingSpringBean() {
6063

@@ -69,6 +72,9 @@ public void collectionAllowsReferencingSpringBean() {
6972
entity.setApplicationContext(context);
7073

7174
assertThat(entity.getCollection(), is("reference"));
75+
76+
provider.collectionName = "otherReference";
77+
assertThat(entity.getCollection(), is("otherReference"));
7278
}
7379

7480
/**

0 commit comments

Comments
 (0)