DATAJPA-1519 - Final polishing.
Introduced dedicated JPA SpEL root object to be able to explicitly control the function names exposed.
This commit is contained in:
@@ -214,16 +214,13 @@ public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensi
|
||||
|
||||
// EvaluationContextExtension for JPA specific SpEL functions
|
||||
|
||||
registerIfNotAlreadyRegistered(() -> {
|
||||
Object value = getEscapeCharacter(config).orElse('\\');
|
||||
|
||||
Object value = getEscapeCharacter(config).orElse('\\');
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(JpaEvaluationContextExtension.class);
|
||||
builder.addConstructorArgValue(value);
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(JpaEvaluationContextExtension.class);
|
||||
builder.addConstructorArgValue(value);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
|
||||
}, registry, JpaEvaluationContextExtension.class.getName(), source);
|
||||
registerIfNotAlreadyRegistered(builder.getBeanDefinition(), registry, JpaEvaluationContextExtension.class.getName(),
|
||||
source);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -34,30 +34,20 @@ public class EscapeCharacter {
|
||||
|
||||
private static final List<String> TO_REPLACE = Arrays.asList("_", "%");
|
||||
|
||||
char value;
|
||||
char escapeCharacter;
|
||||
|
||||
/**
|
||||
* Escapes all special like characters ({@code _}, {@code %}) using the configured escape character.
|
||||
*
|
||||
* @param value May be {@literal null}.
|
||||
* @param value may be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public String escape(String value) {
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return TO_REPLACE.stream() //
|
||||
.reduce(value, (it, character) -> it.replace(character, this.value + character));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the underlying character available.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
public char escapeCharacter() {
|
||||
return value;
|
||||
return value == null //
|
||||
? null //
|
||||
: TO_REPLACE.stream() //
|
||||
.reduce(value, (it, character) -> it.replace(character, this.escapeCharacter + character));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<? extend
|
||||
Expression<String> stringPath = getTypedPath(root, part);
|
||||
Expression<String> propertyExpression = upperIfIgnoreCase(stringPath);
|
||||
Expression<String> parameterExpression = upperIfIgnoreCase(provider.next(part, String.class).getExpression());
|
||||
Predicate like = builder.like(propertyExpression, parameterExpression, escape.getValue());
|
||||
Predicate like = builder.like(propertyExpression, parameterExpression, escape.getEscapeCharacter());
|
||||
return type.equals(NOT_LIKE) || type.equals(NOT_CONTAINING) ? like.not() : like;
|
||||
case TRUE:
|
||||
Expression<Boolean> truePath = getTypedPath(root, part);
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.data.jpa.repository.query.StringQuery.ParameterBindin
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.jpa.repository.support.EscapeCharacter;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.jpa.repository.query.EscapeCharacter;
|
||||
import org.springframework.data.spel.spi.EvaluationContextExtension;
|
||||
import org.springframework.data.repository.query.spi.EvaluationContextExtension;
|
||||
import org.springframework.data.repository.query.spi.EvaluationContextExtensionSupport;
|
||||
|
||||
/**
|
||||
* {@link EvaluationContextExtension} to register {@link EscapeCharacter} as root object to essentially expose an
|
||||
@@ -24,9 +27,9 @@ import org.springframework.data.spel.spi.EvaluationContextExtension;
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
public class JpaEvaluationContextExtension implements EvaluationContextExtension {
|
||||
public class JpaEvaluationContextExtension extends EvaluationContextExtensionSupport {
|
||||
|
||||
private final EscapeCharacter character;
|
||||
private final JpaRootObject root;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaEvaluationContextExtension} for the given escape character.
|
||||
@@ -34,7 +37,7 @@ public class JpaEvaluationContextExtension implements EvaluationContextExtension
|
||||
* @param escapeCharacter the character to be used to escape parameters for LIKE expression.
|
||||
*/
|
||||
public JpaEvaluationContextExtension(char escapeCharacter) {
|
||||
this.character = EscapeCharacter.of(escapeCharacter);
|
||||
this.root = JpaRootObject.of(EscapeCharacter.of(escapeCharacter));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -52,6 +55,32 @@ public class JpaEvaluationContextExtension implements EvaluationContextExtension
|
||||
*/
|
||||
@Override
|
||||
public Object getRootObject() {
|
||||
return character;
|
||||
return root;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor(staticName = "of")
|
||||
public static class JpaRootObject {
|
||||
|
||||
private final EscapeCharacter character;
|
||||
|
||||
/**
|
||||
* Escapes the given source {@link String} for LIKE expressions.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
* @see EscapeCharacter#escape(String)
|
||||
*/
|
||||
public String escape(String source) {
|
||||
return character.escape(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the escape character being used to escape special characters for LIKE expressions.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public char escapeCharacter() {
|
||||
return character.getEscapeCharacter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ package org.springframework.data.jpa.repository.support;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.data.jpa.repository.query.EscapeCharacter;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport;
|
||||
import org.springframework.data.jpa.repository.query.EscapeCharacter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -39,6 +39,8 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
|
||||
extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
|
||||
|
||||
private @Nullable EntityManager entityManager;
|
||||
private EscapeCharacter escapeCharacter = EscapeCharacter.of('\\');
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface.
|
||||
*
|
||||
@@ -48,6 +50,15 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
|
||||
super(repositoryInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the escape character to be used to escape reserved characters in LIKE expressions.
|
||||
*
|
||||
* @param escapeCharacter
|
||||
*/
|
||||
public void setEscapeCharacter(char escapeCharacter) {
|
||||
this.escapeCharacter = EscapeCharacter.of(escapeCharacter);
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link EntityManager} to be used.
|
||||
*
|
||||
@@ -76,7 +87,7 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
|
||||
@Override
|
||||
protected RepositoryFactorySupport doCreateRepositoryFactory() {
|
||||
|
||||
Assert.state(entityManager != null,"EntityManager must not be null!");
|
||||
Assert.state(entityManager != null, "EntityManager must not be null!");
|
||||
|
||||
return createRepositoryFactory(entityManager);
|
||||
}
|
||||
@@ -102,12 +113,7 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
Assert.state(entityManager != null,"EntityManager must not be null!");
|
||||
Assert.state(entityManager != null, "EntityManager must not be null!");
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
public void setEscapeCharacter(char escapeCharacter) {
|
||||
|
||||
this.escapeCharacter = EscapeCharacter.of(escapeCharacter);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user