DATAJPA-1534 - Improved backward compatibility.

Incorporates review feedback by @mp911de.
This commit is contained in:
Jens Schauder
2019-04-29 15:13:22 +02:00
parent 496a3a6eff
commit ac02bc062b
13 changed files with 48 additions and 33 deletions

View File

@@ -76,11 +76,23 @@ public class QueryByExamplePredicateBuilder {
* @param root must not be {@literal null}.
* @param cb must not be {@literal null}.
* @param example must not be {@literal null}.
* @param escapeCharacter
* @return never {@literal null}.
*/
public static <T> Predicate getPredicate(Root<T> root, CriteriaBuilder cb, Example<T> example) {
return getPredicate(root, cb, example, EscapeCharacter.DEFAULT);
}
/**
* Extract the {@link Predicate} representing the {@link Example}.
*
* @param root must not be {@literal null}.
* @param cb must not be {@literal null}.
* @param example must not be {@literal null}.
* @param escapeCharacter Must not be {@literal null}.
* @return never {@literal null}.
*/
public static <T> Predicate getPredicate(Root<T> root, CriteriaBuilder cb, Example<T> example,
EscapeCharacter escapeCharacter) {
EscapeCharacter escapeCharacter) {
Assert.notNull(root, "Root must not be null!");
Assert.notNull(cb, "CriteriaBuilder must not be null!");

View File

@@ -33,6 +33,7 @@ import org.springframework.lang.Nullable;
@Value(staticConstructor = "of")
public class EscapeCharacter {
public static final EscapeCharacter DEFAULT = EscapeCharacter.of('\\');
private static final List<String> TO_REPLACE = Arrays.asList("_", "%");
char escapeCharacter;

View File

@@ -69,7 +69,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
private final CrudMethodMetadataPostProcessor crudMethodMetadataPostProcessor;
private EntityPathResolver entityPathResolver;
private EscapeCharacter escapeCharacter = EscapeCharacter.of('\\');
private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT;
/**
* Creates a new {@link JpaRepositoryFactory}.

View File

@@ -45,7 +45,7 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
private @Nullable EntityManager entityManager;
private EntityPathResolver entityPathResolver;
private EscapeCharacter escapeCharacter = EscapeCharacter.of('\\');
private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT;
/**
* Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface.

View File

@@ -42,5 +42,7 @@ public interface JpaRepositoryImplementation<T, ID> extends JpaRepository<T, ID>
*
* @param escapeCharacter Must not be {@literal null}.
*/
void setEscapeCharacter(EscapeCharacter escapeCharacter);
default void setEscapeCharacter(EscapeCharacter escapeCharacter) {
}
}

View File

@@ -82,7 +82,7 @@ public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T
private final PersistenceProvider provider;
private @Nullable CrudMethodMetadata metadata;
private EscapeCharacter escapeCharacter;
private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT;
/**
* Creates a new {@link SimpleJpaRepository} to manage objects of the given {@link JpaEntityInformation}.

View File

@@ -118,22 +118,22 @@ public class QueryByExamplePredicateBuilderUnitTests {
@Test(expected = IllegalArgumentException.class) // DATAJPA-218
public void getPredicateShouldThrowExceptionOnNullRoot() {
QueryByExamplePredicateBuilder.getPredicate(null, cb, of(new Person()), EscapeCharacter.of('\\'));
QueryByExamplePredicateBuilder.getPredicate(null, cb, of(new Person()), EscapeCharacter.DEFAULT);
}
@Test(expected = IllegalArgumentException.class) // DATAJPA-218
public void getPredicateShouldThrowExceptionOnNullCriteriaBuilder() {
QueryByExamplePredicateBuilder.getPredicate(root, null, of(new Person()), EscapeCharacter.of('\\'));
QueryByExamplePredicateBuilder.getPredicate(root, null, of(new Person()), EscapeCharacter.DEFAULT);
}
@Test(expected = IllegalArgumentException.class) // DATAJPA-218
public void getPredicateShouldThrowExceptionOnNullExample() {
QueryByExamplePredicateBuilder.getPredicate(root, null, null, EscapeCharacter.of('\\'));
QueryByExamplePredicateBuilder.getPredicate(root, null, null, EscapeCharacter.DEFAULT);
}
@Test // DATAJPA-218
public void emptyCriteriaListShouldResultTruePredicate() {
assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, of(new Person()), EscapeCharacter.of('\\')))
assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, of(new Person()), EscapeCharacter.DEFAULT))
.isEqualTo(truePredicate);
}
@@ -143,7 +143,7 @@ public class QueryByExamplePredicateBuilderUnitTests {
Person p = new Person();
p.firstname = "foo";
assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, of(p), EscapeCharacter.of('\\')))
assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, of(p), EscapeCharacter.DEFAULT))
.isEqualTo(dummyPredicate);
verify(cb, times(1)).equal(any(Expression.class), eq("foo"));
}
@@ -157,7 +157,7 @@ public class QueryByExamplePredicateBuilderUnitTests {
p.father = father;
assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(() -> QueryByExamplePredicateBuilder.getPredicate(root, cb, of(p), EscapeCharacter.of('\\')))
.isThrownBy(() -> QueryByExamplePredicateBuilder.getPredicate(root, cb, of(p), EscapeCharacter.DEFAULT))
.withCauseInstanceOf(IllegalArgumentException.class)
.withMessageContaining("Unexpected path type");
}
@@ -169,7 +169,7 @@ public class QueryByExamplePredicateBuilderUnitTests {
p.firstname = "foo";
p.age = 2L;
assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, of(p), EscapeCharacter.of('\\')))
assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, of(p), EscapeCharacter.DEFAULT))
.isEqualTo(andPredicate);
verify(cb, times(1)).equal(any(Expression.class), eq("foo"));
@@ -185,7 +185,7 @@ public class QueryByExamplePredicateBuilderUnitTests {
Example<Person> example = of(person, ExampleMatcher.matchingAny());
assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, example, EscapeCharacter.of('\\')))
assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, example, EscapeCharacter.DEFAULT))
.isEqualTo(orPredicate);
verify(cb, times(1)).or(ArgumentMatchers.any());
@@ -204,7 +204,7 @@ public class QueryByExamplePredicateBuilderUnitTests {
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //
);
QueryByExamplePredicateBuilder.getPredicate(root, cb, example, EscapeCharacter.of('\\'));
QueryByExamplePredicateBuilder.getPredicate(root, cb, example, EscapeCharacter.DEFAULT);
verify(cb, times(1)).like(any(Expression.class), eq("%f\\\\o\\_o%"), eq('\\'));
}
@@ -223,7 +223,7 @@ public class QueryByExamplePredicateBuilderUnitTests {
.withStringMatcher(ExampleMatcher.StringMatcher.STARTING) //
);
QueryByExamplePredicateBuilder.getPredicate(root, cb, example, EscapeCharacter.of('\\'));
QueryByExamplePredicateBuilder.getPredicate(root, cb, example, EscapeCharacter.DEFAULT);
verify(cb, times(1)).like(any(Expression.class), eq("f\\\\o\\_o%"), eq('\\'));
}
@@ -241,7 +241,7 @@ public class QueryByExamplePredicateBuilderUnitTests {
.withStringMatcher(ExampleMatcher.StringMatcher.ENDING) //
);
QueryByExamplePredicateBuilder.getPredicate(root, cb, example, EscapeCharacter.of('\\'));
QueryByExamplePredicateBuilder.getPredicate(root, cb, example, EscapeCharacter.DEFAULT);
verify(cb, times(1)).like(any(Expression.class), eq("%f\\\\o\\_o"), eq('\\'));
}

View File

@@ -60,7 +60,7 @@ public class JpaCountQueryCreatorIntegrationTests {
PartTree tree = new PartTree("findDistinctByRolesIn", User.class);
ParameterMetadataProvider metadataProvider = new ParameterMetadataProvider(entityManager.getCriteriaBuilder(),
queryMethod.getParameters(), provider, EscapeCharacter.of('\\'));
queryMethod.getParameters(), provider, EscapeCharacter.DEFAULT);
JpaCountQueryCreator creator = new JpaCountQueryCreator(tree, queryMethod.getResultProcessor().getReturnedType(),
entityManager.getCriteriaBuilder(), metadataProvider);

View File

@@ -76,7 +76,7 @@ public class JpaQueryLookupStrategyUnitTests {
public void invalidAnnotatedQueryCausesException() throws Exception {
QueryLookupStrategy strategy = JpaQueryLookupStrategy.create(em, Key.CREATE_IF_NOT_FOUND, extractor,
EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.of('\\'));
EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT);
Method method = UserRepository.class.getMethod("findByFoo", String.class);
RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);
@@ -92,7 +92,7 @@ public class JpaQueryLookupStrategyUnitTests {
public void sholdThrowMorePreciseExceptionIfTryingToUsePaginationInNativeQueries() throws Exception {
QueryLookupStrategy strategy = JpaQueryLookupStrategy.create(em, Key.CREATE_IF_NOT_FOUND, extractor,
EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.of('\\'));
EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT);
Method method = UserRepository.class.getMethod("findByInvalidNativeQuery", String.class, Sort.class);
RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);

View File

@@ -58,7 +58,7 @@ public class ParameterExpressionProviderTests {
CriteriaBuilder builder = em.getCriteriaBuilder();
PersistenceProvider persistenceProvider = PersistenceProvider.fromEntityManager(em);
ParameterMetadataProvider provider = new ParameterMetadataProvider(builder, accessor, persistenceProvider, EscapeCharacter.of('\\'));
ParameterMetadataProvider provider = new ParameterMetadataProvider(builder, accessor, persistenceProvider, EscapeCharacter.DEFAULT);
ParameterExpression<? extends Comparable> expression = provider.next(part, Comparable.class).getExpression();
assertThat(expression.getParameterType(), is(typeCompatibleWith(int.class)));
}

View File

@@ -81,7 +81,7 @@ public class ParameterMetadataProviderIntegrationTests {
simulateDiscoveredParametername(parameters);
return new ParameterMetadataProvider(em.getCriteriaBuilder(), parameters,
PersistenceProvider.fromEntityManager(em), EscapeCharacter.of('\\'));
PersistenceProvider.fromEntityManager(em), EscapeCharacter.DEFAULT);
}
@SuppressWarnings({ "unchecked", "ConstantConditions" })

View File

@@ -44,7 +44,7 @@ public class ParameterMetadataProviderUnitTests {
when(parameters.getBindableParameters().iterator()).thenReturn(Collections.emptyListIterator());
ParameterMetadataProvider metadataProvider = new ParameterMetadataProvider(builder, parameters,
persistenceProvider, EscapeCharacter.of('\\'));
persistenceProvider, EscapeCharacter.DEFAULT);
assertThatExceptionOfType(RuntimeException.class) //
.isThrownBy(() -> metadataProvider.next(mock(Part.class))) //

View File

@@ -81,7 +81,7 @@ public class PartTreeJpaQueryIntegrationTests {
public void test() throws Exception {
JpaQueryMethod queryMethod = getQueryMethod("findByFirstname", String.class, Pageable.class);
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.of('\\'));
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.DEFAULT);
jpaQuery.createQuery(new Object[] { "Matthews", PageRequest.of(0, 1) });
jpaQuery.createQuery(new Object[] { "Matthews", PageRequest.of(0, 1) });
@@ -105,7 +105,7 @@ public class PartTreeJpaQueryIntegrationTests {
public void recreatesQueryIfNullValueIsGiven() throws Exception {
JpaQueryMethod queryMethod = getQueryMethod("findByFirstname", String.class, Pageable.class);
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.of('\\'));
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.DEFAULT);
Query query = jpaQuery.createQuery(new Object[] { "Matthews", PageRequest.of(0, 1) });
@@ -120,7 +120,7 @@ public class PartTreeJpaQueryIntegrationTests {
public void shouldLimitExistsProjectionQueries() throws Exception {
JpaQueryMethod queryMethod = getQueryMethod("existsByFirstname", String.class);
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.of('\\'));
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.DEFAULT);
Query query = jpaQuery.createQuery(new Object[] { "Matthews" });
@@ -131,7 +131,7 @@ public class PartTreeJpaQueryIntegrationTests {
public void shouldSelectAliasedIdForExistsProjectionQueries() throws Exception {
JpaQueryMethod queryMethod = getQueryMethod("existsByFirstname", String.class);
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.of('\\'));
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.DEFAULT);
Query query = jpaQuery.createQuery(new Object[] { "Matthews" });
@@ -142,7 +142,7 @@ public class PartTreeJpaQueryIntegrationTests {
public void isEmptyCollection() throws Exception {
JpaQueryMethod queryMethod = getQueryMethod("findByRolesIsEmpty");
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.of('\\'));
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.DEFAULT);
Query query = jpaQuery.createQuery(new Object[] {});
@@ -153,7 +153,7 @@ public class PartTreeJpaQueryIntegrationTests {
public void isNotEmptyCollection() throws Exception {
JpaQueryMethod queryMethod = getQueryMethod("findByRolesIsNotEmpty");
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.of('\\'));
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, provider, EscapeCharacter.DEFAULT);
Query query = jpaQuery.createQuery(new Object[] {});
@@ -164,7 +164,7 @@ public class PartTreeJpaQueryIntegrationTests {
public void rejectsIsEmptyOnNonCollectionProperty() throws Exception {
JpaQueryMethod method = getQueryMethod("findByFirstnameIsEmpty");
AbstractJpaQuery jpaQuery = new PartTreeJpaQuery(method, entityManager, provider, EscapeCharacter.of('\\'));
AbstractJpaQuery jpaQuery = new PartTreeJpaQuery(method, entityManager, provider, EscapeCharacter.DEFAULT);
jpaQuery.createQuery(new Object[] { "Oliver" });
}
@@ -175,7 +175,7 @@ public class PartTreeJpaQueryIntegrationTests {
JpaQueryMethod method = getQueryMethod("findByFirstname");
assertThatExceptionOfType(IllegalArgumentException.class) //
.isThrownBy(() -> new PartTreeJpaQuery(method, entityManager, provider, EscapeCharacter.of('\\'))) //
.isThrownBy(() -> new PartTreeJpaQuery(method, entityManager, provider, EscapeCharacter.DEFAULT)) //
.withMessageContaining("findByFirstname") // the method being analyzed
.withMessageContaining(" firstname ") // the property we are looking for
.withMessageContaining("UserRepository"); // the repository
@@ -187,7 +187,7 @@ public class PartTreeJpaQueryIntegrationTests {
JpaQueryMethod method = getQueryMethod("findByNoSuchProperty", String.class);
assertThatExceptionOfType(IllegalArgumentException.class) //
.isThrownBy(() -> new PartTreeJpaQuery(method, entityManager, provider, EscapeCharacter.of('\\'))) //
.isThrownBy(() -> new PartTreeJpaQuery(method, entityManager, provider, EscapeCharacter.DEFAULT)) //
.withMessageContaining("findByNoSuchProperty") // the method being analyzed
.withMessageContaining(" noSuchProperty ") // the property we are looking for
.withMessageContaining("UserRepository"); // the repository
@@ -203,7 +203,7 @@ public class PartTreeJpaQueryIntegrationTests {
JpaQueryMethod queryMethod = getQueryMethod(methodName, parameterTypes);
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager,
PersistenceProvider.fromEntityManager(entityManager), EscapeCharacter.of('\\'));
PersistenceProvider.fromEntityManager(entityManager), EscapeCharacter.DEFAULT);
jpaQuery.createQuery(values);
}