32
32
import org .springframework .core .ResolvableType ;
33
33
import org .springframework .core .convert .ConversionService ;
34
34
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 ;
35
38
import org .springframework .data .convert .CustomConversions ;
36
39
import org .springframework .data .mapping .InstanceCreatorMetadata ;
37
40
import org .springframework .data .mapping .MappingException ;
41
44
import org .springframework .data .mapping .PersistentPropertyAccessor ;
42
45
import org .springframework .data .mapping .PersistentPropertyPathAccessor ;
43
46
import org .springframework .data .mapping .context .MappingContext ;
47
+ import org .springframework .data .mapping .model .CachingValueExpressionEvaluatorFactory ;
44
48
import org .springframework .data .mapping .model .ConvertingPropertyAccessor ;
45
- import org .springframework .data .mapping .model .DefaultSpELExpressionEvaluator ;
46
49
import org .springframework .data .mapping .model .EntityInstantiator ;
47
50
import org .springframework .data .mapping .model .ParameterValueProvider ;
48
51
import org .springframework .data .mapping .model .PersistentEntityParameterValueProvider ;
49
52
import org .springframework .data .mapping .model .PropertyValueProvider ;
50
53
import org .springframework .data .mapping .model .SimpleTypeHolder ;
51
54
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 ;
54
57
import org .springframework .data .projection .EntityProjection ;
55
58
import org .springframework .data .projection .EntityProjectionIntrospector ;
56
59
import org .springframework .data .projection .EntityProjectionIntrospector .ProjectionPredicate ;
67
70
import org .springframework .data .relational .domain .RowDocument ;
68
71
import org .springframework .data .util .Predicates ;
69
72
import org .springframework .data .util .TypeInformation ;
73
+ import org .springframework .expression .ExpressionParser ;
74
+ import org .springframework .expression .spel .standard .SpelExpressionParser ;
70
75
import org .springframework .lang .Nullable ;
71
76
import org .springframework .util .Assert ;
72
77
import org .springframework .util .ClassUtils ;
84
89
* @see CustomConversions
85
90
* @since 3.2
86
91
*/
87
- public class MappingRelationalConverter extends AbstractRelationalConverter implements ApplicationContextAware {
92
+ public class MappingRelationalConverter extends AbstractRelationalConverter
93
+ implements ApplicationContextAware , EnvironmentCapable {
88
94
89
95
private SpELContext spELContext ;
90
96
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 );
92
103
93
104
private final EntityProjectionIntrospector introspector ;
94
105
106
+ private final CachingValueExpressionEvaluatorFactory valueExpressionEvaluatorFactory = new CachingValueExpressionEvaluatorFactory (
107
+ expressionParser , this , o -> spELContext .getEvaluationContext (o ));
108
+
95
109
/**
96
110
* Creates a new {@link MappingRelationalConverter} given the new {@link RelationalMappingContext}.
97
111
*
@@ -133,10 +147,20 @@ private static EntityProjectionIntrospector createIntrospector(ProjectionFactory
133
147
public void setApplicationContext (ApplicationContext applicationContext ) throws BeansException {
134
148
135
149
this .spELContext = new SpELContext (this .spELContext , applicationContext );
150
+ this .environment = applicationContext .getEnvironment ();
136
151
this .projectionFactory .setBeanFactory (applicationContext );
137
152
this .projectionFactory .setBeanClassLoader (applicationContext .getClassLoader ());
138
153
}
139
154
155
+ @ Override
156
+ public Environment getEnvironment () {
157
+
158
+ if (this .environment == null ) {
159
+ this .environment = new StandardEnvironment ();
160
+ }
161
+ return this .environment ;
162
+ }
163
+
140
164
/**
141
165
* Creates a new {@link ConversionContext}.
142
166
*
@@ -196,7 +220,7 @@ protected <R> R doReadProjection(ConversionContext context, RowDocument document
196
220
TypeInformation <?> mappedType = projection .getActualMappedType ();
197
221
RelationalPersistentEntity <R > mappedEntity = (RelationalPersistentEntity <R >) getMappingContext ()
198
222
.getPersistentEntity (mappedType );
199
- SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator (document , spELContext );
223
+ ValueExpressionEvaluator evaluator = valueExpressionEvaluatorFactory . create (document );
200
224
201
225
boolean isInterfaceProjection = mappedType .getType ().isInterface ();
202
226
if (isInterfaceProjection ) {
@@ -432,7 +456,7 @@ private <T> T doConvert(Object value, Class<? extends T> target, @Nullable Class
432
456
private <S > S read (ConversionContext context , RelationalPersistentEntity <S > entity ,
433
457
RowDocumentAccessor documentAccessor ) {
434
458
435
- SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator (documentAccessor .getDocument (), spELContext );
459
+ ValueExpressionEvaluator evaluator = valueExpressionEvaluatorFactory . create (documentAccessor .getDocument ());
436
460
437
461
InstanceCreatorMetadata <RelationalPersistentProperty > instanceCreatorMetadata = entity .getInstanceCreatorMetadata ();
438
462
@@ -455,7 +479,7 @@ public <T> T createInstance(PersistentEntity<T, RelationalPersistentProperty> en
455
479
}
456
480
457
481
private ParameterValueProvider <RelationalPersistentProperty > getParameterProvider (ConversionContext context ,
458
- RelationalPersistentEntity <?> entity , RowDocumentAccessor source , SpELExpressionEvaluator evaluator ) {
482
+ RelationalPersistentEntity <?> entity , RowDocumentAccessor source , ValueExpressionEvaluator evaluator ) {
459
483
460
484
// Ensure that ConversionContext is contextualized to the current property.
461
485
RelationalPropertyValueProvider contextualizing = new RelationalPropertyValueProvider () {
@@ -489,12 +513,12 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {
489
513
PersistentEntityParameterValueProvider <RelationalPersistentProperty > parameterProvider = new PersistentEntityParameterValueProvider <>(
490
514
entity , contextualizing , context .getPath ().getCurrentObject ());
491
515
492
- return new ConverterAwareSpELExpressionParameterValueProvider (context , evaluator , getConversionService (),
516
+ return new ConverterAwareExpressionParameterValueProvider (context , evaluator , getConversionService (),
493
517
new ConvertingParameterValueProvider <>(parameterProvider ::getParameterValue ));
494
518
}
495
519
496
520
private <S > S populateProperties (ConversionContext context , RelationalPersistentEntity <S > entity ,
497
- RowDocumentAccessor documentAccessor , SpELExpressionEvaluator evaluator , S instance ) {
521
+ RowDocumentAccessor documentAccessor , ValueExpressionEvaluator evaluator , S instance ) {
498
522
499
523
if (!entity .requiresPropertyPopulation ()) {
500
524
return instance ;
@@ -516,7 +540,7 @@ private <S> S populateProperties(ConversionContext context, RelationalPersistent
516
540
}
517
541
518
542
protected RelationalPropertyValueProvider newValueProvider (RowDocumentAccessor documentAccessor ,
519
- SpELExpressionEvaluator evaluator , ConversionContext context ) {
543
+ ValueExpressionEvaluator evaluator , ConversionContext context ) {
520
544
return new DocumentValueProvider (context , documentAccessor , evaluator , spELContext );
521
545
}
522
546
@@ -1059,22 +1083,22 @@ protected static final class DocumentValueProvider
1059
1083
1060
1084
private final ConversionContext context ;
1061
1085
private final RowDocumentAccessor accessor ;
1062
- private final SpELExpressionEvaluator evaluator ;
1086
+ private final ValueExpressionEvaluator evaluator ;
1063
1087
private final SpELContext spELContext ;
1064
1088
1065
1089
/**
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 }.
1067
1091
*
1068
1092
* @param context must not be {@literal null}.
1069
1093
* @param accessor must not be {@literal null}.
1070
1094
* @param evaluator must not be {@literal null}.
1071
1095
*/
1072
1096
private DocumentValueProvider (ConversionContext context , RowDocumentAccessor accessor ,
1073
- SpELExpressionEvaluator evaluator , SpELContext spELContext ) {
1097
+ ValueExpressionEvaluator evaluator , SpELContext spELContext ) {
1074
1098
1075
1099
Assert .notNull (context , "ConversionContext must no be null" );
1076
1100
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" );
1078
1102
this .context = context ;
1079
1103
this .accessor = accessor ;
1080
1104
this .evaluator = evaluator ;
@@ -1166,24 +1190,24 @@ public <T> T getParameterValue(Parameter<T, P> parameter) {
1166
1190
}
1167
1191
1168
1192
/**
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
1170
1194
* resolved SpEL value.
1171
1195
*/
1172
- private static class ConverterAwareSpELExpressionParameterValueProvider
1173
- extends SpELExpressionParameterValueProvider <RelationalPersistentProperty > {
1196
+ private static class ConverterAwareExpressionParameterValueProvider
1197
+ extends ValueExpressionParameterValueProvider <RelationalPersistentProperty > {
1174
1198
1175
1199
private final ConversionContext context ;
1176
1200
1177
1201
/**
1178
- * Creates a new {@link ConverterAwareSpELExpressionParameterValueProvider }.
1202
+ * Creates a new {@link ConverterAwareExpressionParameterValueProvider }.
1179
1203
*
1180
1204
* @param context must not be {@literal null}.
1181
1205
* @param evaluator must not be {@literal null}.
1182
1206
* @param conversionService must not be {@literal null}.
1183
1207
* @param delegate must not be {@literal null}.
1184
1208
*/
1185
- public ConverterAwareSpELExpressionParameterValueProvider (ConversionContext context ,
1186
- SpELExpressionEvaluator evaluator , ConversionService conversionService ,
1209
+ public ConverterAwareExpressionParameterValueProvider (ConversionContext context , ValueExpressionEvaluator evaluator ,
1210
+ ConversionService conversionService ,
1187
1211
ParameterValueProvider <RelationalPersistentProperty > delegate ) {
1188
1212
1189
1213
super (evaluator , conversionService , delegate );
@@ -1194,9 +1218,11 @@ public ConverterAwareSpELExpressionParameterValueProvider(ConversionContext cont
1194
1218
}
1195
1219
1196
1220
@ Override
1197
- protected <T > T potentiallyConvertSpelValue (Object object , Parameter <T , RelationalPersistentProperty > parameter ) {
1221
+ protected <T > T potentiallyConvertExpressionValue (Object object ,
1222
+ Parameter <T , RelationalPersistentProperty > parameter ) {
1198
1223
return context .convert (object , parameter .getType ());
1199
1224
}
1225
+
1200
1226
}
1201
1227
1202
1228
private record PropertyTranslatingPropertyAccessor <T >(PersistentPropertyAccessor <T > delegate ,
0 commit comments