@ -32,6 +32,9 @@ import org.springframework.core.CollectionFactory;
@@ -32,6 +32,9 @@ import org.springframework.core.CollectionFactory;
import org.springframework.core.ResolvableType ;
import org.springframework.core.convert.ConversionService ;
import org.springframework.core.convert.TypeDescriptor ;
import org.springframework.core.env.Environment ;
import org.springframework.core.env.EnvironmentCapable ;
import org.springframework.core.env.StandardEnvironment ;
import org.springframework.data.convert.CustomConversions ;
import org.springframework.data.mapping.InstanceCreatorMetadata ;
import org.springframework.data.mapping.MappingException ;
@ -41,16 +44,16 @@ import org.springframework.data.mapping.PersistentProperty;
@@ -41,16 +44,16 @@ import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor ;
import org.springframework.data.mapping.PersistentPropertyPathAccessor ;
import org.springframework.data.mapping.context.MappingContext ;
import org.springframework.data.mapping.model.CachingValueExpressionEvaluatorFactory ;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor ;
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator ;
import org.springframework.data.mapping.model.EntityInstantiator ;
import org.springframework.data.mapping.model.ParameterValueProvider ;
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider ;
import org.springframework.data.mapping.model.PropertyValueProvider ;
import org.springframework.data.mapping.model.SimpleTypeHolder ;
import org.springframework.data.mapping.model.SpELContext ;
import org.springframework.data.mapping.model.SpEL ExpressionEvaluator ;
import org.springframework.data.mapping.model.SpEL ExpressionParameterValueProvider ;
import org.springframework.data.mapping.model.Value ExpressionEvaluator ;
import org.springframework.data.mapping.model.Value ExpressionParameterValueProvider ;
import org.springframework.data.projection.EntityProjection ;
import org.springframework.data.projection.EntityProjectionIntrospector ;
import org.springframework.data.projection.EntityProjectionIntrospector.ProjectionPredicate ;
@ -67,6 +70,8 @@ import org.springframework.data.relational.core.sql.SqlIdentifier;
@@ -67,6 +70,8 @@ import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.relational.domain.RowDocument ;
import org.springframework.data.util.Predicates ;
import org.springframework.data.util.TypeInformation ;
import org.springframework.expression.ExpressionParser ;
import org.springframework.expression.spel.standard.SpelExpressionParser ;
import org.springframework.lang.Nullable ;
import org.springframework.util.Assert ;
import org.springframework.util.ClassUtils ;
@ -84,14 +89,23 @@ import org.springframework.util.ClassUtils;
@@ -84,14 +89,23 @@ import org.springframework.util.ClassUtils;
* @see CustomConversions
* @since 3 . 2
* /
public class MappingRelationalConverter extends AbstractRelationalConverter implements ApplicationContextAware {
public class MappingRelationalConverter extends AbstractRelationalConverter
implements ApplicationContextAware , EnvironmentCapable {
private SpELContext spELContext ;
private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory ( ) ;
private @Nullable Environment environment ;
private final ExpressionParser expressionParser = new SpelExpressionParser ( ) ;
private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory (
expressionParser ) ;
private final EntityProjectionIntrospector introspector ;
private final CachingValueExpressionEvaluatorFactory valueExpressionEvaluatorFactory = new CachingValueExpressionEvaluatorFactory (
expressionParser , this , o - > spELContext . getEvaluationContext ( o ) ) ;
/ * *
* Creates a new { @link MappingRelationalConverter } given the new { @link RelationalMappingContext } .
*
@ -133,10 +147,20 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -133,10 +147,20 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
public void setApplicationContext ( ApplicationContext applicationContext ) throws BeansException {
this . spELContext = new SpELContext ( this . spELContext , applicationContext ) ;
this . environment = applicationContext . getEnvironment ( ) ;
this . projectionFactory . setBeanFactory ( applicationContext ) ;
this . projectionFactory . setBeanClassLoader ( applicationContext . getClassLoader ( ) ) ;
}
@Override
public Environment getEnvironment ( ) {
if ( this . environment = = null ) {
this . environment = new StandardEnvironment ( ) ;
}
return this . environment ;
}
/ * *
* Creates a new { @link ConversionContext } .
*
@ -196,7 +220,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -196,7 +220,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
TypeInformation < ? > mappedType = projection . getActualMappedType ( ) ;
RelationalPersistentEntity < R > mappedEntity = ( RelationalPersistentEntity < R > ) getMappingContext ( )
. getPersistentEntity ( mappedType ) ;
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator ( document , spELContex t) ;
ValueExpressionEvaluator evaluator = valueExpressionEvaluatorFactory . create ( documen t) ;
boolean isInterfaceProjection = mappedType . getType ( ) . isInterface ( ) ;
if ( isInterfaceProjection ) {
@ -432,7 +456,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -432,7 +456,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
private < S > S read ( ConversionContext context , RelationalPersistentEntity < S > entity ,
RowDocumentAccessor documentAccessor ) {
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator ( documentAccessor . getDocument ( ) , spELContext ) ;
ValueExpressionEvaluator evaluator = valueExpressionEvaluatorFactory . create ( documentAccessor . getDocument ( ) ) ;
InstanceCreatorMetadata < RelationalPersistentProperty > instanceCreatorMetadata = entity . getInstanceCreatorMetadata ( ) ;
@ -455,7 +479,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -455,7 +479,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
}
private ParameterValueProvider < RelationalPersistentProperty > getParameterProvider ( ConversionContext context ,
RelationalPersistentEntity < ? > entity , RowDocumentAccessor source , SpEL ExpressionEvaluator evaluator ) {
RelationalPersistentEntity < ? > entity , RowDocumentAccessor source , Value ExpressionEvaluator evaluator ) {
// Ensure that ConversionContext is contextualized to the current property.
RelationalPropertyValueProvider contextualizing = new RelationalPropertyValueProvider ( ) {
@ -489,12 +513,12 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -489,12 +513,12 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
PersistentEntityParameterValueProvider < RelationalPersistentProperty > parameterProvider = new PersistentEntityParameterValueProvider < > (
entity , contextualizing , context . getPath ( ) . getCurrentObject ( ) ) ;
return new ConverterAwareSpEL ExpressionParameterValueProvider ( context , evaluator , getConversionService ( ) ,
return new ConverterAwareExpressionParameterValueProvider ( context , evaluator , getConversionService ( ) ,
new ConvertingParameterValueProvider < > ( parameterProvider : : getParameterValue ) ) ;
}
private < S > S populateProperties ( ConversionContext context , RelationalPersistentEntity < S > entity ,
RowDocumentAccessor documentAccessor , SpEL ExpressionEvaluator evaluator , S instance ) {
RowDocumentAccessor documentAccessor , Value ExpressionEvaluator evaluator , S instance ) {
if ( ! entity . requiresPropertyPopulation ( ) ) {
return instance ;
@ -516,7 +540,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -516,7 +540,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
}
protected RelationalPropertyValueProvider newValueProvider ( RowDocumentAccessor documentAccessor ,
SpEL ExpressionEvaluator evaluator , ConversionContext context ) {
Value ExpressionEvaluator evaluator , ConversionContext context ) {
return new DocumentValueProvider ( context , documentAccessor , evaluator , spELContext ) ;
}
@ -1059,22 +1083,22 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -1059,22 +1083,22 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
private final ConversionContext context ;
private final RowDocumentAccessor accessor ;
private final SpEL ExpressionEvaluator evaluator ;
private final Value ExpressionEvaluator evaluator ;
private final SpELContext spELContext ;
/ * *
* Creates a new { @link RelationalPropertyValueProvider } for the given source and { @link SpEL ExpressionEvaluator} .
* Creates a new { @link RelationalPropertyValueProvider } for the given source and { @link Value ExpressionEvaluator} .
*
* @param context must not be { @literal null } .
* @param accessor must not be { @literal null } .
* @param evaluator must not be { @literal null } .
* /
private DocumentValueProvider ( ConversionContext context , RowDocumentAccessor accessor ,
SpEL ExpressionEvaluator evaluator , SpELContext spELContext ) {
Value ExpressionEvaluator evaluator , SpELContext spELContext ) {
Assert . notNull ( context , "ConversionContext must no be null" ) ;
Assert . notNull ( accessor , "DocumentAccessor must no be null" ) ;
Assert . notNull ( evaluator , "SpEL ExpressionEvaluator must not be null" ) ;
Assert . notNull ( evaluator , "Value ExpressionEvaluator must not be null" ) ;
this . context = context ;
this . accessor = accessor ;
this . evaluator = evaluator ;
@ -1166,24 +1190,24 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -1166,24 +1190,24 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
}
/ * *
* Extension of { @link SpEL ExpressionParameterValueProvider} to recursively trigger value conversion on the raw
* Extension of { @link Value ExpressionParameterValueProvider} to recursively trigger value conversion on the raw
* resolved SpEL value .
* /
private static class ConverterAwareSpEL ExpressionParameterValueProvider
extends SpEL ExpressionParameterValueProvider< RelationalPersistentProperty > {
private static class ConverterAwareExpressionParameterValueProvider
extends Value ExpressionParameterValueProvider< RelationalPersistentProperty > {
private final ConversionContext context ;
/ * *
* Creates a new { @link ConverterAwareSpEL ExpressionParameterValueProvider } .
* Creates a new { @link ConverterAwareExpressionParameterValueProvider } .
*
* @param context must not be { @literal null } .
* @param evaluator must not be { @literal null } .
* @param conversionService must not be { @literal null } .
* @param delegate must not be { @literal null } .
* /
public ConverterAwareSpEL ExpressionParameterValueProvider ( ConversionContext context ,
SpELExpressionEvaluator evaluator , ConversionService conversionService ,
public ConverterAwareExpressionParameterValueProvider ( ConversionContext context , ValueExpressionEvaluator evaluator ,
ConversionService conversionService ,
ParameterValueProvider < RelationalPersistentProperty > delegate ) {
super ( evaluator , conversionService , delegate ) ;
@ -1194,9 +1218,11 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
@@ -1194,9 +1218,11 @@ public class MappingRelationalConverter extends AbstractRelationalConverter impl
}
@Override
protected < T > T potentiallyConvertSpelValue ( Object object , Parameter < T , RelationalPersistentProperty > parameter ) {
protected < T > T potentiallyConvertExpressionValue ( Object object ,
Parameter < T , RelationalPersistentProperty > parameter ) {
return context . convert ( object , parameter . getType ( ) ) ;
}
}
private record PropertyTranslatingPropertyAccessor < T > ( PersistentPropertyAccessor < T > delegate ,