DATACMNS-669 - Added support to bind Querydsl Predicates to Spring MVC controllers.
Adding @QuerydslPredicate to a parameter within SpringMVC Controller when having registered the QueryDslPredicateArgumentResolver allows to generate a Querydsl Predicate based on the request parameters.
Parameters will be converted into their corresponding property types before using the as predicate value. Given more than one attribute will connect those using 'and'. Collections of values will force usage of 'in' while single values on collection like properties result in 'contains'.
The base type for building the Querydsl Path is extracted from the methods return type. In case of non domain type return values it can optionally be specified via @QueydslPredicate(root = …). Specific Predicate conversions can be registered via '@QuerydslSpecification'.
This allows to sneak in specific property path handlings more easily.
new QueryDslPredicateSpecification() {
{
define(new StringPath("address.city"), (path, value) -> path.like(value.toString()));
}
};
Renamed resolver, accessor etc. to express operation of binding properties to a resolved path and introduced explicit binding context which allows reuse of predicate builder within the ArgumentResolver.
Added registration of QuerydslPredicateArgumentResolver directly in SpringDataWebConfiguration reusing the provided ConversionService.
Added Javadoc and changed visibility of non public API and types.
Original pull request: #132.
This commit is contained in:
committed by
Oliver Gierke
parent
30b4cf53fc
commit
e645501174
27
src/test/java/org/springframework/data/querydsl/Address.java
Normal file
27
src/test/java/org/springframework/data/querydsl/Address.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.querydsl;
|
||||
|
||||
import com.mysema.query.annotations.QueryEntity;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@QueryEntity
|
||||
public class Address {
|
||||
String street;
|
||||
String city;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,16 +16,23 @@
|
||||
package org.springframework.data.querydsl;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.mysema.query.annotations.QueryEntity;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@QueryEntity
|
||||
public class User {
|
||||
|
||||
String firstname;
|
||||
String lastname;
|
||||
Date dateOfBirth;
|
||||
|
||||
Address address;
|
||||
List<String> nickNames;
|
||||
Long inceptionYear;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.web.querydsl;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.hamcrest.core.IsNull.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.querydsl.Address;
|
||||
import org.springframework.data.querydsl.QAddress;
|
||||
import org.springframework.data.querydsl.User;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
|
||||
import com.mysema.query.types.Predicate;
|
||||
import com.mysema.query.types.path.StringPath;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link QuerydslBindings}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class QuerydslBindingsUnitTests {
|
||||
|
||||
private QuerydslPredicateBuilder builder;
|
||||
private QuerydslBindings typeBasedBindings;
|
||||
private QuerydslBindings pathBasedBindings;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
builder = new QuerydslPredicateBuilder();
|
||||
|
||||
typeBasedBindings = new QuerydslBindings() {
|
||||
{
|
||||
bind(String.class, new QuerydslBinding<StringPath>() {
|
||||
|
||||
@Override
|
||||
public Predicate bind(StringPath path, Object value) {
|
||||
return path.contains(value.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
pathBasedBindings = new QuerydslBindings() {
|
||||
{
|
||||
bind("address.street", new QuerydslBinding<StringPath>() {
|
||||
|
||||
@Override
|
||||
public Predicate bind(StringPath path, Object value) {
|
||||
return path.contains(value.toString());
|
||||
}
|
||||
});
|
||||
|
||||
bind("firstname", new QuerydslBinding<StringPath>() {
|
||||
|
||||
@Override
|
||||
public Predicate bind(StringPath path, Object value) {
|
||||
return path.contains(value.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getBindingForPathShouldThrowErrorWhenPathIsNull() {
|
||||
pathBasedBindings.getBindingForPath(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void getBindingForPathShouldReturnNullWhenNoSpecifcBindingAvailable() {
|
||||
assertThat(pathBasedBindings.getBindingForPath(PropertyPath.from("lastname", User.class)), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void getBindingForPathShouldReturnSpeficicBindingWhenAvailable() {
|
||||
assertThat(pathBasedBindings.getBindingForPath(PropertyPath.from("firstname", User.class)), notNullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void getBindingForPathShouldReturnSpeficicBindingForNestedElementsWhenAvailable() {
|
||||
assertThat(pathBasedBindings.getBindingForPath(PropertyPath.from("address.street", User.class)), notNullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void getBindingForPathShouldReturnSpeficicBindingForTypes() {
|
||||
assertThat(typeBasedBindings.getBindingForPath(PropertyPath.from("address.street", User.class)), notNullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void getBindingForPathShouldIgnoreSpeficicBindingForTypesWhenTypesDoNotMatch() {
|
||||
assertThat(typeBasedBindings.getBindingForPath(PropertyPath.from("inceptionYear", User.class)), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnTrueWhenNoRestrictionDefined() {
|
||||
assertThat(typeBasedBindings.isPathVisible(PropertyPath.from("inceptionYear", User.class)), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnTrueWhenPathContainedInIncluding() {
|
||||
|
||||
assertThat(
|
||||
new QuerydslBindings().including("inceptionYear").isPathVisible(PropertyPath.from("inceptionYear", User.class)),
|
||||
is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnFalseWhenPathNotContainedInIncluding() {
|
||||
|
||||
assertThat(
|
||||
new QuerydslBindings().including("inceptionYear").isPathVisible(PropertyPath.from("firstname", User.class)),
|
||||
is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnFalseWhenPathContainedInExcluding() {
|
||||
|
||||
assertThat(
|
||||
new QuerydslBindings().excluding("inceptionYear").isPathVisible(PropertyPath.from("inceptionYear", User.class)),
|
||||
is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnTrueWhenPathNotContainedInExcluding() {
|
||||
|
||||
assertThat(
|
||||
new QuerydslBindings().excluding("inceptionYear").isPathVisible(PropertyPath.from("firstname", User.class)),
|
||||
is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnTrueWhenPathContainedInExcludingAndIncluding() {
|
||||
|
||||
assertThat(
|
||||
new QuerydslBindings().excluding("inceptionYear").isPathVisible(PropertyPath.from("firstname", User.class)),
|
||||
is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnFalseWhenPartialPathContainedInExcluding() {
|
||||
|
||||
assertThat(
|
||||
new QuerydslBindings().excluding("address").isPathVisible(PropertyPath.from("address.city", User.class)),
|
||||
is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnTrueWhenPartialPathContainedInExcludingButConcretePathIsIncluded() {
|
||||
|
||||
assertThat(
|
||||
new QuerydslBindings().excluding("address").including("address.city")
|
||||
.isPathVisible(PropertyPath.from("address.city", User.class)), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void isPathVisibleShouldReturnFalseWhenPartialPathContainedInExcludingAndConcretePathToDifferentPropertyIsIncluded() {
|
||||
|
||||
assertThat(
|
||||
new QuerydslBindings().excluding("address").including("address.city")
|
||||
.isPathVisible(PropertyPath.from("address.street", User.class)), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void usesTypeBasedBindingIfConfigured() {
|
||||
|
||||
MutablePropertyValues values = new MutablePropertyValues(Collections.singletonMap("city", "Dresden"));
|
||||
|
||||
QuerydslBindingContext context = new QuerydslBindingContext(ClassTypeInformation.from(Address.class),
|
||||
this.typeBasedBindings, null);
|
||||
|
||||
assertThat(builder.getPredicate(values, context), is((Predicate) QAddress.address.city.contains("Dresden")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.web.querydsl;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.core.Is;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.querydsl.QUser;
|
||||
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.Predicate;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class QuerydslDefaultBindingUnitTests {
|
||||
|
||||
QuerydslDefaultBinding builder;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
builder = new QuerydslDefaultBinding();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void shouldCreatePredicateCorrectlyWhenPropertyIsInRoot() {
|
||||
|
||||
Predicate predicate = builder.bind(QUser.user.firstname, "tam");
|
||||
|
||||
assertThat(predicate, is(QUser.user.firstname.eq("tam")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void shouldCreatePredicateCorrectlyWhenPropertyIsInNestedElement() {
|
||||
|
||||
Predicate predicate = builder.bind(QUser.user.address.city, "two rivers");
|
||||
|
||||
Assert.assertThat(predicate.toString(), is(QUser.user.address.city.eq("two rivers").toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void shouldCreatePredicateCorrectlyWhenValueIsNull() {
|
||||
|
||||
Predicate predicate = builder.bind(QUser.user.firstname, null);
|
||||
|
||||
assertThat(predicate, is(QUser.user.firstname.isNull()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void shouldCreatePredicateWithContainingWhenPropertyIsCollectionLikeAndValueIsObject() {
|
||||
|
||||
Predicate predicate = builder.bind(QUser.user.nickNames, "dragon reborn");
|
||||
|
||||
assertThat(predicate, is(QUser.user.nickNames.contains("dragon reborn")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void shouldCreatePredicateWithInWhenPropertyIsAnObjectAndValueIsACollection() {
|
||||
|
||||
Predicate predicate = builder.bind(QUser.user.firstname, Arrays.asList("dragon reborn", "shadowkiller"));
|
||||
|
||||
assertThat(predicate, is(QUser.user.firstname.in(Arrays.asList("dragon reborn", "shadowkiller"))));
|
||||
}
|
||||
|
||||
/*
|
||||
* just to satisfy generic type boundaries o_O
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private void assertThat(Predicate predicate, Matcher<? extends Expression> matcher) {
|
||||
Assert.assertThat((Expression) predicate, Is.<Expression> is((Matcher<Expression>) matcher));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.web.querydsl;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.hamcrest.core.Is;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.querydsl.QUser;
|
||||
import org.springframework.data.querydsl.User;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
import com.mysema.query.types.Predicate;
|
||||
import com.mysema.query.types.expr.BooleanExpression;
|
||||
import com.mysema.query.types.path.StringPath;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
|
||||
QuerydslPredicateArgumentResolver resolver;
|
||||
MockHttpServletRequest request;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
resolver = new QuerydslPredicateArgumentResolver(null);
|
||||
request = new MockHttpServletRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void supportsParameterReturnsTrueWhenMethodParameterIsPredicateAndAnnotatedCorrectly() {
|
||||
assertThat(resolver.supportsParameter(getMethodParameterFor("simpleFind", Predicate.class)), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void supportsParameterReturnsTrueWhenMethodParameterIsPredicateButNotAnnotatedAsSuch() {
|
||||
assertThat(resolver.supportsParameter(getMethodParameterFor("predicateWithoutAnnotation", Predicate.class)),
|
||||
is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void supportsParameterShouldThrowExceptionWhenMethodParameterIsNoPredicateButAnnotatedAsSuch() {
|
||||
resolver.supportsParameter(getMethodParameterFor("nonPredicateWithAnnotation", String.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void supportsParameterReturnsFalseWhenMethodParameterIsNoPredicate() {
|
||||
assertThat(resolver.supportsParameter(getMethodParameterFor("nonPredicateWithoutAnnotation", String.class)),
|
||||
is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void resolveArgumentShouldCreateSingleStringParameterPredicateCorrectly() throws Exception {
|
||||
|
||||
request.addParameter("firstname", "rand");
|
||||
|
||||
Object predicate = (BooleanExpression) resolver.resolveArgument(
|
||||
getMethodParameterFor("simpleFind", Predicate.class), null, new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate, Is.<Object> is(QUser.user.firstname.eq("rand")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void resolveArgumentShouldCreateMultipleParametersPredicateCorrectly() throws Exception {
|
||||
|
||||
request.addParameter("firstname", "rand");
|
||||
request.addParameter("lastname", "al'thor");
|
||||
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("simpleFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate, Is.<Object> is(QUser.user.firstname.eq("rand").and(QUser.user.lastname.eq("al'thor"))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void resolveArgumentShouldCreateNestedObjectPredicateCorrectly() throws Exception {
|
||||
|
||||
request.addParameter("address.city", "two rivers");
|
||||
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("simpleFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate.toString(), is(QUser.user.address.city.eq("two rivers").toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void resolveArgumentShouldResolveTypePropertyFromPageCorrectly() throws Exception {
|
||||
|
||||
request.addParameter("address.city", "tar valon");
|
||||
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("pagedFind", Predicate.class, Pageable.class),
|
||||
null, new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate.toString(), is(QUser.user.address.city.eq("tar valon").toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void resolveArgumentShouldHonorCustomSpeficifcation() throws Exception {
|
||||
|
||||
request.addParameter("firstname", "egwene");
|
||||
request.addParameter("lastname", "al'vere");
|
||||
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("specificFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate.toString(),
|
||||
is(QUser.user.firstname.eq("egwene".toUpperCase()).and(QUser.user.lastname.toLowerCase().eq("al'vere"))
|
||||
.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void shouldCreatePredicateForNonStringPropertyCorrectly() throws Exception {
|
||||
|
||||
request.addParameter("inceptionYear", "978");
|
||||
|
||||
Object predicate = (BooleanExpression) resolver.resolveArgument(
|
||||
getMethodParameterFor("specificFind", Predicate.class), null, new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate, Is.<Object> is(QUser.user.inceptionYear.eq(978L)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void shouldCreatePredicateForNonStringListPropertyCorrectly() throws Exception {
|
||||
|
||||
request.addParameter("inceptionYear", new String[] { "978", "998" });
|
||||
|
||||
Object predicate = (BooleanExpression) resolver.resolveArgument(
|
||||
getMethodParameterFor("specificFind", Predicate.class), null, new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate, Is.<Object> is(QUser.user.inceptionYear.in(978L, 998L)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void shouldExcludePorpertiesCorrectly() throws Exception {
|
||||
|
||||
request.addParameter("address.street", "downhill");
|
||||
request.addParameter("inceptionYear", "973");
|
||||
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("specificFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate.toString(), is(QUser.user.inceptionYear.eq(973L).toString()));
|
||||
}
|
||||
|
||||
private MethodParameter getMethodParameterFor(String methodName, Class<?>... args) throws RuntimeException {
|
||||
|
||||
try {
|
||||
return new MethodParameter(Sample.class.getMethod(methodName, args), 0);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static class SpecificBinding extends QuerydslBindings {
|
||||
|
||||
public SpecificBinding() {
|
||||
|
||||
bind("firstname", new QuerydslBinding<StringPath>() {
|
||||
|
||||
@Override
|
||||
public Predicate bind(StringPath path, Object value) {
|
||||
return path.eq(value.toString().toUpperCase());
|
||||
}
|
||||
});
|
||||
|
||||
bind(QUser.user.lastname, new QuerydslBinding<StringPath>() {
|
||||
|
||||
@Override
|
||||
public Predicate bind(StringPath path, Object value) {
|
||||
return path.toLowerCase().eq(value.toString());
|
||||
}
|
||||
});
|
||||
|
||||
excluding("address");
|
||||
}
|
||||
}
|
||||
|
||||
static interface Sample {
|
||||
|
||||
User predicateWithoutAnnotation(Predicate predicate);
|
||||
|
||||
User nonPredicateWithAnnotation(@QuerydslPredicate String predicate);
|
||||
|
||||
User nonPredicateWithoutAnnotation(String predicate);
|
||||
|
||||
User simpleFind(@QuerydslPredicate Predicate predicate);
|
||||
|
||||
Page<User> pagedFind(@QuerydslPredicate Predicate predicate, Pageable page);
|
||||
|
||||
User specificFind(@QuerydslPredicate(bindings = SpecificBinding.class) Predicate predicate);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.web.querydsl;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.hamcrest.core.Is;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.data.querydsl.QUser;
|
||||
import org.springframework.data.querydsl.User;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
|
||||
import com.mysema.query.BooleanBuilder;
|
||||
import com.mysema.query.types.Predicate;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class QuerydslPredicateBuilderUnitTests {
|
||||
|
||||
QuerydslPredicateBuilder builder;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
builder = new QuerydslPredicateBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getPredicateShouldThrowErrorWhenBindingContextIsNull() {
|
||||
builder.getPredicate(new MutablePropertyValues(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void getPredicateShouldReturnEmptyPredicateWhenPropertiesAreEmpty() {
|
||||
|
||||
assertThat(builder.getPredicate(new MutablePropertyValues(), new QuerydslBindingContext(
|
||||
ClassTypeInformation.OBJECT, null, null)), is((Predicate) new BooleanBuilder()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-669
|
||||
*/
|
||||
@Test
|
||||
public void resolveArgumentShouldCreateSingleStringParameterPredicateCorrectly() throws Exception {
|
||||
|
||||
Predicate predicate = builder.getPredicate(
|
||||
new MutablePropertyValues(Collections.singletonMap("firstname", new String[] { "rand" })),
|
||||
new QuerydslBindingContext(ClassTypeInformation.from(User.class), null, null));
|
||||
|
||||
assertThat(predicate, Is.<Object> is(QUser.user.firstname.eq("rand")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user