@@ -32,9 +32,13 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.EnvironmentCapable;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.cassandra.core.mapping.*;
|
||||
import org.springframework.data.cassandra.core.mapping.Embedded.OnEmpty;
|
||||
@@ -46,19 +50,20 @@ import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
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.PropertyValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELContext;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.ValueExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.ValueExpressionParameterValueProvider;
|
||||
import org.springframework.data.projection.EntityProjection;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.util.Predicates;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -87,7 +92,7 @@ import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
|
||||
* @author Frank Spitulski
|
||||
*/
|
||||
public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
implements ApplicationContextAware, BeanClassLoaderAware {
|
||||
implements ApplicationContextAware, EnvironmentAware, EnvironmentCapable, BeanClassLoaderAware {
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -99,11 +104,21 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
|
||||
private @Nullable ClassLoader beanClassLoader;
|
||||
|
||||
private @Nullable Environment environment;
|
||||
|
||||
private SpELContext spELContext;
|
||||
|
||||
private final DefaultColumnTypeResolver cassandraTypeResolver;
|
||||
|
||||
private final EmbeddedEntityOperations embeddedEntityOperations;
|
||||
private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory();
|
||||
|
||||
private final SpelExpressionParser expressionParser = new SpelExpressionParser();
|
||||
|
||||
private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory(
|
||||
expressionParser);
|
||||
|
||||
private final CachingValueExpressionEvaluatorFactory expressionEvaluatorFactory = new CachingValueExpressionEvaluatorFactory(
|
||||
expressionParser, this, o -> spELContext.getEvaluationContext(o));
|
||||
|
||||
/**
|
||||
* Create a new {@link MappingCassandraConverter} with a {@link CassandraMappingContext}.
|
||||
@@ -171,10 +186,30 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
this.spELContext = new SpELContext(this.spELContext, applicationContext);
|
||||
this.environment = applicationContext.getEnvironment();
|
||||
this.projectionFactory.setBeanFactory(applicationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment getEnvironment() {
|
||||
|
||||
if (this.environment == null) {
|
||||
this.environment = new StandardEnvironment();
|
||||
}
|
||||
return this.environment;
|
||||
}
|
||||
|
||||
public void setSpELContext(SpELContext spELContext) {
|
||||
this.spELContext = spELContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
@@ -294,8 +329,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
this::doReadTupleValue, this::doReadUdtValue, this::readCollectionOrArray, this::readMap,
|
||||
this::getPotentiallyConvertedSimpleRead, projection);
|
||||
|
||||
return doReadProjection(context, new RowValueProvider(row, new DefaultSpELExpressionEvaluator(row, spELContext)),
|
||||
projection);
|
||||
return doReadProjection(context, new RowValueProvider(row, expressionEvaluatorFactory.create(row)), projection);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -334,11 +368,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
|
||||
ParameterValueProvider<CassandraPersistentProperty> provider;
|
||||
if (persistenceCreator != null && persistenceCreator.hasParameters()) {
|
||||
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(valueProviderToUse.getSource(),
|
||||
spELContext);
|
||||
ValueExpressionEvaluator evaluator = expressionEvaluatorFactory.create(valueProviderToUse.getSource());
|
||||
ParameterValueProvider<CassandraPersistentProperty> parameterValueProvider = newParameterValueProvider(context,
|
||||
entity, valueProviderToUse);
|
||||
provider = new ConverterAwareSpELExpressionParameterValueProvider(evaluator, getConversionService(),
|
||||
provider = new ConverterAwareValueExpressionParameterValueProvider(evaluator, getConversionService(),
|
||||
parameterValueProvider, context);
|
||||
} else {
|
||||
provider = NoOpParameterValueProvider.INSTANCE;
|
||||
@@ -362,8 +395,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
|
||||
if (typeDescriptor.isProjection()) {
|
||||
|
||||
CassandraValueProvider valueProvider = new RowValueProvider(row,
|
||||
new DefaultSpELExpressionEvaluator(row, this.spELContext));
|
||||
CassandraValueProvider valueProvider = new RowValueProvider(row, expressionEvaluatorFactory.create(row));
|
||||
return doReadProjection(context, valueProvider, typeDescriptor);
|
||||
}
|
||||
|
||||
@@ -376,7 +408,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
if (typeDescriptor.isProjection()) {
|
||||
|
||||
CassandraValueProvider valueProvider = new UdtValueProvider(udtValue,
|
||||
new DefaultSpELExpressionEvaluator(udtValue, this.spELContext));
|
||||
expressionEvaluatorFactory.create(udtValue));
|
||||
return doReadProjection(context, valueProvider, typeDescriptor);
|
||||
}
|
||||
|
||||
@@ -389,7 +421,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
if (typeDescriptor.isProjection()) {
|
||||
|
||||
CassandraValueProvider valueProvider = new TupleValueProvider(tupleValue,
|
||||
new DefaultSpELExpressionEvaluator(tupleValue, this.spELContext));
|
||||
expressionEvaluatorFactory.create(tupleValue));
|
||||
return doReadProjection(context, valueProvider, typeDescriptor);
|
||||
}
|
||||
|
||||
@@ -436,10 +468,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
}
|
||||
|
||||
private <S> S doReadEntity(ConversionContext context, Object value,
|
||||
Function<SpELExpressionEvaluator, CassandraValueProvider> valueProviderSupplier,
|
||||
Function<ValueExpressionEvaluator, CassandraValueProvider> valueProviderSupplier,
|
||||
TypeInformation<? extends S> typeHint) {
|
||||
|
||||
SpELExpressionEvaluator expressionEvaluator = new DefaultSpELExpressionEvaluator(value, this.spELContext);
|
||||
ValueExpressionEvaluator expressionEvaluator = expressionEvaluatorFactory.create(value);
|
||||
CassandraValueProvider valueProvider = valueProviderSupplier.apply(expressionEvaluator);
|
||||
|
||||
return doReadEntity(context, valueProvider, typeHint);
|
||||
@@ -507,10 +539,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
ParameterValueProvider<CassandraPersistentProperty> provider;
|
||||
|
||||
if (persistenceCreator != null && persistenceCreator.hasParameters()) {
|
||||
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(valueProvider.getSource(), spELContext);
|
||||
ValueExpressionEvaluator evaluator = expressionEvaluatorFactory.create(valueProvider.getSource());
|
||||
ParameterValueProvider<CassandraPersistentProperty> parameterValueProvider = newParameterValueProvider(context,
|
||||
entity, valueProvider);
|
||||
provider = new ConverterAwareSpELExpressionParameterValueProvider(evaluator, getConversionService(),
|
||||
provider = new ConverterAwareValueExpressionParameterValueProvider(evaluator, getConversionService(),
|
||||
parameterValueProvider, context);
|
||||
} else {
|
||||
provider = NoOpParameterValueProvider.INSTANCE;
|
||||
@@ -1261,23 +1293,23 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension of {@link SpELExpressionParameterValueProvider} to recursively trigger value conversion on the raw
|
||||
* Extension of {@link ValueExpressionParameterValueProvider} to recursively trigger value conversion on the raw
|
||||
* resolved SpEL value.
|
||||
*/
|
||||
private static class ConverterAwareSpELExpressionParameterValueProvider
|
||||
extends SpELExpressionParameterValueProvider<CassandraPersistentProperty> {
|
||||
private static class ConverterAwareValueExpressionParameterValueProvider
|
||||
extends ValueExpressionParameterValueProvider<CassandraPersistentProperty> {
|
||||
|
||||
private final ConversionContext context;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConverterAwareSpELExpressionParameterValueProvider}.
|
||||
* Creates a new {@link ConverterAwareValueExpressionParameterValueProvider}.
|
||||
*
|
||||
* @param evaluator must not be {@literal null}.
|
||||
* @param conversionService must not be {@literal null}.
|
||||
* @param delegate must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
*/
|
||||
public ConverterAwareSpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator,
|
||||
public ConverterAwareValueExpressionParameterValueProvider(ValueExpressionEvaluator evaluator,
|
||||
ConversionService conversionService, ParameterValueProvider<CassandraPersistentProperty> delegate,
|
||||
ConversionContext context) {
|
||||
|
||||
@@ -1286,8 +1318,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, CassandraPersistentProperty> parameter) {
|
||||
return (T) context.convert(object, parameter.getType());
|
||||
protected <T> T potentiallyConvertExpressionValue(Object object,
|
||||
Parameter<T, CassandraPersistentProperty> parameter) {
|
||||
return context.convert(object, parameter.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.springframework.data.cassandra.core.convert;
|
||||
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.ValueExpressionEvaluator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -33,16 +33,16 @@ public class RowValueProvider implements CassandraValueProvider {
|
||||
|
||||
private final RowReader reader;
|
||||
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
private final ValueExpressionEvaluator evaluator;
|
||||
|
||||
/**
|
||||
* Create a new {@link RowValueProvider} with the given {@link Row}, {@link CodecRegistry} and
|
||||
* {@link SpELExpressionEvaluator}.
|
||||
* {@link ValueExpressionEvaluator}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param evaluator must not be {@literal null}.
|
||||
*/
|
||||
public RowValueProvider(Row source, SpELExpressionEvaluator evaluator) {
|
||||
public RowValueProvider(Row source, ValueExpressionEvaluator evaluator) {
|
||||
|
||||
Assert.notNull(source, "Source Row must not be null");
|
||||
Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null");
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.springframework.data.cassandra.core.convert;
|
||||
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.ValueExpressionEvaluator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -34,17 +34,17 @@ public class TupleValueProvider implements CassandraValueProvider {
|
||||
|
||||
private final CodecRegistry codecRegistry;
|
||||
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
private final ValueExpressionEvaluator evaluator;
|
||||
|
||||
private final TupleValue tupleValue;
|
||||
|
||||
/**
|
||||
* Create a new {@link TupleValueProvider} with the given {@link TupleValue} and {@link SpELExpressionEvaluator}.
|
||||
* Create a new {@link TupleValueProvider} with the given {@link TupleValue} and {@link ValueExpressionEvaluator}.
|
||||
*
|
||||
* @param tupleValue must not be {@literal null}.
|
||||
* @param evaluator must not be {@literal null}.
|
||||
*/
|
||||
public TupleValueProvider(TupleValue tupleValue, SpELExpressionEvaluator evaluator) {
|
||||
public TupleValueProvider(TupleValue tupleValue, ValueExpressionEvaluator evaluator) {
|
||||
|
||||
Assert.notNull(tupleValue, "TupleValue must not be null");
|
||||
Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null");
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.springframework.data.cassandra.core.convert;
|
||||
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.ValueExpressionEvaluator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -32,15 +32,15 @@ public class UdtValueProvider implements CassandraValueProvider {
|
||||
|
||||
private final UdtValue udtValue;
|
||||
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
private final ValueExpressionEvaluator evaluator;
|
||||
|
||||
/**
|
||||
* Create a new {@link UdtValueProvider} with the given {@link UdtValue} and {@link SpELExpressionEvaluator}.
|
||||
* Create a new {@link UdtValueProvider} with the given {@link UdtValue} and {@link ValueExpressionEvaluator}.
|
||||
*
|
||||
* @param udtValue must not be {@literal null}.
|
||||
* @param evaluator must not be {@literal null}.
|
||||
*/
|
||||
public UdtValueProvider(UdtValue udtValue, SpELExpressionEvaluator evaluator) {
|
||||
public UdtValueProvider(UdtValue udtValue, ValueExpressionEvaluator evaluator) {
|
||||
|
||||
Assert.notNull(udtValue, "UDTValue must not be null");
|
||||
Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null");
|
||||
|
||||
@@ -23,18 +23,23 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryAccessor;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.data.expression.ValueEvaluationContext;
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.Parameter;
|
||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -52,18 +57,20 @@ import com.datastax.oss.driver.api.core.CqlIdentifier;
|
||||
public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T, CassandraPersistentProperty>
|
||||
implements CassandraPersistentEntity<T>, ApplicationContextAware {
|
||||
|
||||
static final ValueExpressionParser PARSER = ValueExpressionParser.create(SpelExpressionParser::new);
|
||||
|
||||
private static final CassandraPersistentEntityMetadataVerifier DEFAULT_VERIFIER = new CompositeCassandraPersistentEntityMetadataVerifier();
|
||||
|
||||
private final CqlIdentifierGenerator namingAccessor = new CqlIdentifierGenerator();
|
||||
|
||||
private @Nullable ApplicationContext applicationContext;
|
||||
|
||||
private Boolean forceQuote;
|
||||
|
||||
private CassandraPersistentEntityMetadataVerifier verifier = DEFAULT_VERIFIER;
|
||||
|
||||
private CqlIdentifier tableName;
|
||||
|
||||
private @Nullable StandardEvaluationContext spelContext;
|
||||
|
||||
private final Map<Parameter<?, CassandraPersistentProperty>, CassandraPersistentProperty> constructorProperties = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
@@ -117,11 +124,45 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
|
||||
|
||||
if (annotation != null) {
|
||||
return this.namingAccessor.generate((String) AnnotationUtils.getValue(annotation),
|
||||
(Boolean) AnnotationUtils.getValue(annotation, "forceQuote"), defaultNameGenerator, this, this.spelContext);
|
||||
(Boolean) AnnotationUtils.getValue(annotation, "forceQuote"), defaultNameGenerator, this, PARSER,
|
||||
this::getValueEvaluationContext);
|
||||
}
|
||||
|
||||
return this.namingAccessor.generate(null, forceQuote != null ? forceQuote : false, defaultNameGenerator, this,
|
||||
this.spelContext);
|
||||
PARSER, this::getValueEvaluationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EvaluationContext getEvaluationContext(Object rootObject) {
|
||||
return postProcess(super.getEvaluationContext(rootObject == null ? applicationContext : rootObject));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EvaluationContext getEvaluationContext(Object rootObject, ExpressionDependencies dependencies) {
|
||||
return postProcess(super.getEvaluationContext(rootObject == null ? applicationContext : rootObject, dependencies));
|
||||
}
|
||||
|
||||
// TODO: Do we want to keep the Context customization? Ideally, we align with EvaluationContextProvider.
|
||||
private EvaluationContext postProcess(EvaluationContext evaluationContext) {
|
||||
|
||||
if (evaluationContext instanceof StandardEvaluationContext sec) {
|
||||
|
||||
if (sec.getRootObject().getValue() instanceof BeanFactory) {
|
||||
sec.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
}
|
||||
}
|
||||
|
||||
return evaluationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValueEvaluationContext getValueEvaluationContext(Object rootObject) {
|
||||
return super.getValueEvaluationContext(rootObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValueEvaluationContext getValueEvaluationContext(Object rootObject, ExpressionDependencies dependencies) {
|
||||
return super.getValueEvaluationContext(rootObject, dependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,13 +192,7 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
|
||||
Assert.notNull(context, "ApplicationContext must not be null");
|
||||
|
||||
spelContext = new StandardEvaluationContext();
|
||||
spelContext.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
spelContext.setBeanResolver(new BeanFactoryResolver(context));
|
||||
spelContext.setRootObject(context);
|
||||
this.applicationContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,8 +25,6 @@ import java.util.Optional;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryAccessor;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.data.cassandra.core.cql.Ordering;
|
||||
import org.springframework.data.cassandra.core.cql.PrimaryKeyType;
|
||||
@@ -36,7 +34,6 @@ import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -64,8 +61,6 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
|
||||
private @Nullable CqlIdentifier columnName;
|
||||
|
||||
private @Nullable StandardEvaluationContext spelContext;
|
||||
|
||||
/**
|
||||
* Create a new {@link BasicCassandraPersistentProperty}.
|
||||
*
|
||||
@@ -80,15 +75,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) {
|
||||
|
||||
Assert.notNull(context, "ApplicationContext must not be null");
|
||||
|
||||
this.spelContext = new StandardEvaluationContext();
|
||||
this.spelContext.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
this.spelContext.setBeanResolver(new BeanFactoryResolver(context));
|
||||
this.spelContext.setRootObject(context);
|
||||
}
|
||||
public void setApplicationContext(ApplicationContext context) {}
|
||||
|
||||
@Override
|
||||
public CassandraPersistentEntity<?> getOwner() {
|
||||
@@ -175,7 +162,10 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
forceQuote = column.forceQuote();
|
||||
}
|
||||
|
||||
return namingAccessor.generate(overriddenName, forceQuote, NamingStrategy::getColumnName, this, this.spelContext);
|
||||
BasicCassandraPersistentEntity<?> entity = (BasicCassandraPersistentEntity<?>) getOwner();
|
||||
|
||||
return namingAccessor.generate(overriddenName, forceQuote, NamingStrategy::getColumnName, this,
|
||||
BasicCassandraPersistentEntity.PARSER, entity::getValueEvaluationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,10 +18,13 @@ package org.springframework.data.cassandra.core.mapping;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.data.cassandra.util.SpelUtils;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.data.expression.ValueEvaluationContext;
|
||||
import org.springframework.data.expression.ValueExpression;
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlIdentifier;
|
||||
@@ -59,18 +62,21 @@ class CqlIdentifierGenerator {
|
||||
* @param forceQuote whether to enforce quoting.
|
||||
* @param defaultNameGenerator the default name generator.
|
||||
* @param source source to be used for name generation.
|
||||
* @param spelContext the SpEL evaluation context for evaluating SpEL expressions provided through
|
||||
* {@code providedName}.
|
||||
* @param parser expression parser.
|
||||
* @param contextFunction evaluation context provider function.
|
||||
* @return the generated name.
|
||||
*/
|
||||
public <T> CqlIdentifier generate(@Nullable String providedName, boolean forceQuote,
|
||||
BiFunction<NamingStrategy, T, String> defaultNameGenerator, T source, @Nullable EvaluationContext spelContext) {
|
||||
BiFunction<NamingStrategy, T, String> defaultNameGenerator, T source, ValueExpressionParser parser,
|
||||
BiFunction<Object, ExpressionDependencies, ValueEvaluationContext> contextFunction) {
|
||||
|
||||
String name;
|
||||
boolean useForceQuote = forceQuote;
|
||||
|
||||
if (StringUtils.hasText(providedName)) {
|
||||
name = spelContext != null ? SpelUtils.evaluate(providedName, spelContext) : providedName;
|
||||
ValueExpression expression = parser.parse(providedName);
|
||||
name = ObjectUtils
|
||||
.nullSafeToString(expression.evaluate(contextFunction.apply(null, expression.getExpressionDependencies())));
|
||||
useForceQuote = true;
|
||||
} else {
|
||||
name = defaultNameGenerator.apply(getNamingStrategy(forceQuote), source);
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlIdentifier;
|
||||
@@ -81,6 +82,7 @@ class BasicCassandraPersistentEntityUnitTests {
|
||||
|
||||
BasicCassandraPersistentEntity<UserLine> entity = new BasicCassandraPersistentEntity<>(
|
||||
TypeInformation.of(UserLine.class));
|
||||
entity.setEvaluationContextProvider(new ExtensionAwareEvaluationContextProvider(context));
|
||||
entity.setApplicationContext(context);
|
||||
|
||||
assertThat(entity.getTableName()).hasToString(bean.tableName);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
** xref:cassandra/property-converters.adoc[]
|
||||
** xref:cassandra/events.adoc[]
|
||||
** xref:cassandra/auditing.adoc[]
|
||||
** xref:cassandra/value-expressions.adoc[]
|
||||
|
||||
* xref:repositories.adoc[]
|
||||
** xref:repositories/core-concepts.adoc[]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include::{commons}@data-commons::page$value-expressions.adoc[]
|
||||
Reference in New Issue
Block a user