3232import org .springframework .core .ResolvableType ;
3333import org .springframework .core .convert .ConversionService ;
3434import 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 ;
3538import org .springframework .data .convert .CustomConversions ;
3639import org .springframework .data .mapping .InstanceCreatorMetadata ;
3740import org .springframework .data .mapping .MappingException ;
4144import org .springframework .data .mapping .PersistentPropertyAccessor ;
4245import org .springframework .data .mapping .PersistentPropertyPathAccessor ;
4346import org .springframework .data .mapping .context .MappingContext ;
47+ import org .springframework .data .mapping .model .CachingValueExpressionEvaluatorFactory ;
4448import org .springframework .data .mapping .model .ConvertingPropertyAccessor ;
45- import org .springframework .data .mapping .model .DefaultSpELExpressionEvaluator ;
4649import org .springframework .data .mapping .model .EntityInstantiator ;
4750import org .springframework .data .mapping .model .ParameterValueProvider ;
4851import org .springframework .data .mapping .model .PersistentEntityParameterValueProvider ;
4952import org .springframework .data .mapping .model .PropertyValueProvider ;
5053import org .springframework .data .mapping .model .SimpleTypeHolder ;
5154import 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 ;
5457import org .springframework .data .projection .EntityProjection ;
5558import org .springframework .data .projection .EntityProjectionIntrospector ;
5659import org .springframework .data .projection .EntityProjectionIntrospector .ProjectionPredicate ;
6770import org .springframework .data .relational .domain .RowDocument ;
6871import org .springframework .data .util .Predicates ;
6972import org .springframework .data .util .TypeInformation ;
73+ import org .springframework .expression .ExpressionParser ;
74+ import org .springframework .expression .spel .standard .SpelExpressionParser ;
7075import org .springframework .lang .Nullable ;
7176import org .springframework .util .Assert ;
7277import org .springframework .util .ClassUtils ;
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