Skip to content

Commit 7ac5c66

Browse files
committed
Add support for ValueExpression.
Closes #1738
1 parent 1fbf9a3 commit 7ac5c66

File tree

2 files changed

+51
-24
lines changed

2 files changed

+51
-24
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.apache.commons.logging.Log;
2828
import org.apache.commons.logging.LogFactory;
29+
2930
import org.springframework.context.ApplicationContextAware;
3031
import org.springframework.core.convert.ConverterNotFoundException;
3132
import org.springframework.core.convert.converter.Converter;
@@ -35,7 +36,7 @@
3536
import org.springframework.data.jdbc.support.JdbcUtil;
3637
import org.springframework.data.mapping.context.MappingContext;
3738
import org.springframework.data.mapping.model.SimpleTypeHolder;
38-
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
39+
import org.springframework.data.mapping.model.ValueExpressionEvaluator;
3940
import org.springframework.data.relational.core.conversion.MappingRelationalConverter;
4041
import org.springframework.data.relational.core.conversion.ObjectPath;
4142
import org.springframework.data.relational.core.conversion.RelationalConverter;
@@ -289,7 +290,7 @@ public <R> R readAndResolve(Class<R> type, RowDocument source, Identifier identi
289290

290291
@Override
291292
protected RelationalPropertyValueProvider newValueProvider(RowDocumentAccessor documentAccessor,
292-
SpELExpressionEvaluator evaluator, ConversionContext context) {
293+
ValueExpressionEvaluator evaluator, ConversionContext context) {
293294

294295
if (context instanceof ResolvingConversionContext rcc) {
295296

spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/MappingRelationalConverter.java

+48-22
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
import org.springframework.core.ResolvableType;
3333
import org.springframework.core.convert.ConversionService;
3434
import org.springframework.core.convert.TypeDescriptor;
35+
import org.springframework.core.env.Environment;
36+
import org.springframework.core.env.EnvironmentCapable;
37+
import org.springframework.core.env.StandardEnvironment;
3538
import org.springframework.data.convert.CustomConversions;
3639
import org.springframework.data.mapping.InstanceCreatorMetadata;
3740
import org.springframework.data.mapping.MappingException;
@@ -41,16 +44,16 @@
4144
import org.springframework.data.mapping.PersistentPropertyAccessor;
4245
import org.springframework.data.mapping.PersistentPropertyPathAccessor;
4346
import org.springframework.data.mapping.context.MappingContext;
47+
import org.springframework.data.mapping.model.CachingValueExpressionEvaluatorFactory;
4448
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
45-
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
4649
import org.springframework.data.mapping.model.EntityInstantiator;
4750
import org.springframework.data.mapping.model.ParameterValueProvider;
4851
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
4952
import org.springframework.data.mapping.model.PropertyValueProvider;
5053
import org.springframework.data.mapping.model.SimpleTypeHolder;
5154
import org.springframework.data.mapping.model.SpELContext;
52-
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
53-
import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider;
55+
import org.springframework.data.mapping.model.ValueExpressionEvaluator;
56+
import org.springframework.data.mapping.model.ValueExpressionParameterValueProvider;
5457
import org.springframework.data.projection.EntityProjection;
5558
import org.springframework.data.projection.EntityProjectionIntrospector;
5659
import org.springframework.data.projection.EntityProjectionIntrospector.ProjectionPredicate;
@@ -67,6 +70,8 @@
6770
import org.springframework.data.relational.domain.RowDocument;
6871
import org.springframework.data.util.Predicates;
6972
import org.springframework.data.util.TypeInformation;
73+
import org.springframework.expression.ExpressionParser;
74+
import org.springframework.expression.spel.standard.SpelExpressionParser;
7075
import org.springframework.lang.Nullable;
7176
import org.springframework.util.Assert;
7277
import org.springframework.util.ClassUtils;
@@ -84,14 +89,23 @@
8489
* @see CustomConversions
8590
* @since 3.2
8691
*/
87-
public class MappingRelationalConverter extends AbstractRelationalConverter implements ApplicationContextAware {
92+
public class MappingRelationalConverter extends AbstractRelationalConverter
93+
implements ApplicationContextAware, EnvironmentCapable {
8894

8995
private SpELContext spELContext;
9096

91-
private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory();
97+
private @Nullable Environment environment;
98+
99+
private final ExpressionParser expressionParser = new SpelExpressionParser();
100+
101+
private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory(
102+
expressionParser);
92103

93104
private final EntityProjectionIntrospector introspector;
94105

106+
private final CachingValueExpressionEvaluatorFactory valueExpressionEvaluatorFactory = new CachingValueExpressionEvaluatorFactory(
107+
expressionParser, this, o -> spELContext.getEvaluationContext(o));
108+
95109
/**
96110
* Creates a new {@link MappingRelationalConverter} given the new {@link RelationalMappingContext}.
97111
*
@@ -133,10 +147,20 @@ private static EntityProjectionIntrospector createIntrospector(ProjectionFactory
133147
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
134148

135149
this.spELContext = new SpELContext(this.spELContext, applicationContext);
150+
this.environment = applicationContext.getEnvironment();
136151
this.projectionFactory.setBeanFactory(applicationContext);
137152
this.projectionFactory.setBeanClassLoader(applicationContext.getClassLoader());
138153
}
139154

155+
@Override
156+
public Environment getEnvironment() {
157+
158+
if (this.environment == null) {
159+
this.environment = new StandardEnvironment();
160+
}
161+
return this.environment;
162+
}
163+
140164
/**
141165
* Creates a new {@link ConversionContext}.
142166
*
@@ -196,7 +220,7 @@ protected <R> R doReadProjection(ConversionContext context, RowDocument document
196220
TypeInformation<?> mappedType = projection.getActualMappedType();
197221
RelationalPersistentEntity<R> mappedEntity = (RelationalPersistentEntity<R>) getMappingContext()
198222
.getPersistentEntity(mappedType);
199-
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(document, spELContext);
223+
ValueExpressionEvaluator evaluator = valueExpressionEvaluatorFactory.create(document);
200224

201225
boolean isInterfaceProjection = mappedType.getType().isInterface();
202226
if (isInterfaceProjection) {
@@ -432,7 +456,7 @@ private <T> T doConvert(Object value, Class<? extends T> target, @Nullable Class
432456
private <S> S read(ConversionContext context, RelationalPersistentEntity<S> entity,
433457
RowDocumentAccessor documentAccessor) {
434458

435-
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(documentAccessor.getDocument(), spELContext);
459+
ValueExpressionEvaluator evaluator = valueExpressionEvaluatorFactory.create(documentAccessor.getDocument());
436460

437461
InstanceCreatorMetadata<RelationalPersistentProperty> instanceCreatorMetadata = entity.getInstanceCreatorMetadata();
438462

@@ -455,7 +479,7 @@ public <T> T createInstance(PersistentEntity<T, RelationalPersistentProperty> en
455479
}
456480

457481
private ParameterValueProvider<RelationalPersistentProperty> getParameterProvider(ConversionContext context,
458-
RelationalPersistentEntity<?> entity, RowDocumentAccessor source, SpELExpressionEvaluator evaluator) {
482+
RelationalPersistentEntity<?> entity, RowDocumentAccessor source, ValueExpressionEvaluator evaluator) {
459483

460484
// Ensure that ConversionContext is contextualized to the current property.
461485
RelationalPropertyValueProvider contextualizing = new RelationalPropertyValueProvider() {
@@ -489,12 +513,12 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {
489513
PersistentEntityParameterValueProvider<RelationalPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<>(
490514
entity, contextualizing, context.getPath().getCurrentObject());
491515

492-
return new ConverterAwareSpELExpressionParameterValueProvider(context, evaluator, getConversionService(),
516+
return new ConverterAwareExpressionParameterValueProvider(context, evaluator, getConversionService(),
493517
new ConvertingParameterValueProvider<>(parameterProvider::getParameterValue));
494518
}
495519

496520
private <S> S populateProperties(ConversionContext context, RelationalPersistentEntity<S> entity,
497-
RowDocumentAccessor documentAccessor, SpELExpressionEvaluator evaluator, S instance) {
521+
RowDocumentAccessor documentAccessor, ValueExpressionEvaluator evaluator, S instance) {
498522

499523
if (!entity.requiresPropertyPopulation()) {
500524
return instance;
@@ -516,7 +540,7 @@ private <S> S populateProperties(ConversionContext context, RelationalPersistent
516540
}
517541

518542
protected RelationalPropertyValueProvider newValueProvider(RowDocumentAccessor documentAccessor,
519-
SpELExpressionEvaluator evaluator, ConversionContext context) {
543+
ValueExpressionEvaluator evaluator, ConversionContext context) {
520544
return new DocumentValueProvider(context, documentAccessor, evaluator, spELContext);
521545
}
522546

@@ -1059,22 +1083,22 @@ protected static final class DocumentValueProvider
10591083

10601084
private final ConversionContext context;
10611085
private final RowDocumentAccessor accessor;
1062-
private final SpELExpressionEvaluator evaluator;
1086+
private final ValueExpressionEvaluator evaluator;
10631087
private final SpELContext spELContext;
10641088

10651089
/**
1066-
* Creates a new {@link RelationalPropertyValueProvider} for the given source and {@link SpELExpressionEvaluator}.
1090+
* Creates a new {@link RelationalPropertyValueProvider} for the given source and {@link ValueExpressionEvaluator}.
10671091
*
10681092
* @param context must not be {@literal null}.
10691093
* @param accessor must not be {@literal null}.
10701094
* @param evaluator must not be {@literal null}.
10711095
*/
10721096
private DocumentValueProvider(ConversionContext context, RowDocumentAccessor accessor,
1073-
SpELExpressionEvaluator evaluator, SpELContext spELContext) {
1097+
ValueExpressionEvaluator evaluator, SpELContext spELContext) {
10741098

10751099
Assert.notNull(context, "ConversionContext must no be null");
10761100
Assert.notNull(accessor, "DocumentAccessor must no be null");
1077-
Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null");
1101+
Assert.notNull(evaluator, "ValueExpressionEvaluator must not be null");
10781102
this.context = context;
10791103
this.accessor = accessor;
10801104
this.evaluator = evaluator;
@@ -1166,24 +1190,24 @@ public <T> T getParameterValue(Parameter<T, P> parameter) {
11661190
}
11671191

11681192
/**
1169-
* Extension of {@link SpELExpressionParameterValueProvider} to recursively trigger value conversion on the raw
1193+
* Extension of {@link ValueExpressionParameterValueProvider} to recursively trigger value conversion on the raw
11701194
* resolved SpEL value.
11711195
*/
1172-
private static class ConverterAwareSpELExpressionParameterValueProvider
1173-
extends SpELExpressionParameterValueProvider<RelationalPersistentProperty> {
1196+
private static class ConverterAwareExpressionParameterValueProvider
1197+
extends ValueExpressionParameterValueProvider<RelationalPersistentProperty> {
11741198

11751199
private final ConversionContext context;
11761200

11771201
/**
1178-
* Creates a new {@link ConverterAwareSpELExpressionParameterValueProvider}.
1202+
* Creates a new {@link ConverterAwareExpressionParameterValueProvider}.
11791203
*
11801204
* @param context must not be {@literal null}.
11811205
* @param evaluator must not be {@literal null}.
11821206
* @param conversionService must not be {@literal null}.
11831207
* @param delegate must not be {@literal null}.
11841208
*/
1185-
public ConverterAwareSpELExpressionParameterValueProvider(ConversionContext context,
1186-
SpELExpressionEvaluator evaluator, ConversionService conversionService,
1209+
public ConverterAwareExpressionParameterValueProvider(ConversionContext context, ValueExpressionEvaluator evaluator,
1210+
ConversionService conversionService,
11871211
ParameterValueProvider<RelationalPersistentProperty> delegate) {
11881212

11891213
super(evaluator, conversionService, delegate);
@@ -1194,9 +1218,11 @@ public ConverterAwareSpELExpressionParameterValueProvider(ConversionContext cont
11941218
}
11951219

11961220
@Override
1197-
protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, RelationalPersistentProperty> parameter) {
1221+
protected <T> T potentiallyConvertExpressionValue(Object object,
1222+
Parameter<T, RelationalPersistentProperty> parameter) {
11981223
return context.convert(object, parameter.getType());
11991224
}
1225+
12001226
}
12011227

12021228
private record PropertyTranslatingPropertyAccessor<T>(PersistentPropertyAccessor<T> delegate,

0 commit comments

Comments
 (0)