یکی دیگر از روش های کوئری Search / Filter در REST Api استفاده از Spring Data QueryDSL Web Support است که در این بخش به آن میپردازیم
ابتدا کتابخانه های مورد نیاز را به پروژه اضافه میکنیم :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
...
* اگر از کتابخانه Spring-Data-Commons ورژن 1.11 به بالا استفاده میکنیم نیاز نیست که کتابخانه QueryDSL web support را جداگانه اضافه کنیم
مرحله بعد Repository را میسازیم :
public interface UserRepository extends
JpaRepository<User, Long>, QueryDslPredicateExecutor<User>, QuerydslBinderCustomizer<QUser> {
@Override
default public void customize(QuerydslBindings bindings, QUser root) {
bindings.bind(String.class).first(
(StringPath path, String value) -> path.containsIgnoreCase(value));
bindings.excluding(root.email);
}
}
دقت کنید که در کد بالا متد customize از کلای QuerydslBinderCustomizer را Override کردیم تا bind کنند پیش فرض را ایجاد کنیم و مقادیر از نوع String در Binder سفارشی بصورت IgnoreCase تعریف کردیم که بزرگ و کوچک بودن رشته ها در عملیات بی تاثیر باشند
سپس email کاربر را از bind خارج کردیم
ساخت User Controller :
@RequestMapping(method = RequestMethod.GET, value = "/users")
@ResponseBody
public Iterable<User> findAllByWebQuerydsl(
@QuerydslPredicate(root = User.class) Predicate predicate) {
return userRepository.findAll(predicate);
}
قسمت جالب کد بالا ساخته شدن اتوماتیک Predicate توسط QuerydslPredicate@ است
ارسال درخواست توسط کلاینت :
http://localhost:8080/users?firstName=john
ساختار پاسخ دریافتی کلاینت :
[
{
"id":1,
"firstName":"john",
"lastName":"doe",
"email":"john@test.com",
"age":11
}
]
تست :
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class UserLiveTest {
private ObjectMapper mapper = new ObjectMapper();
private User userJohn = new User("john", "doe", "john@test.com");
private User userTom = new User("tom", "doe", "tom@test.com");
private static boolean setupDataCreated = false;
@Before
public void setupData() throws JsonProcessingException {
if (!setupDataCreated) {
givenAuth().contentType(MediaType.APPLICATION_JSON_VALUE)
.body(mapper.writeValueAsString(userJohn))
.post("http://localhost:8080/users");
givenAuth().contentType(MediaType.APPLICATION_JSON_VALUE)
.body(mapper.writeValueAsString(userTom))
.post("http://localhost:8080/users");
setupDataCreated = true;
}
}
private RequestSpecification givenAuth() {
return RestAssured.given().auth().preemptive().basic("user1", "user1Pass");
}
}
تست کوئری دریافت کلیه User ها :
@Test
public void whenGettingListOfUsers_thenCorrect() {
Response response = givenAuth().get("http://localhost:8080/users");
User[] result = response.as(User[].class);
assertEquals(result.length, 2);
}
تست کوئری پیدا کردن User بر اساس firstName :
@Test
public void givenFirstName_whenGettingListOfUsers_thenCorrect() {
Response response = givenAuth().get("http://localhost:8080/users?firstName=john");
User[] result = response.as(User[].class);
assertEquals(result.length, 1);
assertEquals(result[0].getEmail(), userJohn.getEmail());
}
تست کوئری پیدا کردن User بر اساس قسمتی از lastName :
@Test
public void givenPartialLastName_whenGettingListOfUsers_thenCorrect() {
Response response = givenAuth().get("http://localhost:8080/users?lastName=do");
User[] result = response.as(User[].class);
assertEquals(result.length, 2);
}
تست کوئری بر اساس ایمیل User :
@Test
public void givenEmail_whenGettingListOfUsers_thenIgnored() {
Response response = givenAuth().get("http://localhost:8080/users?email=john");
User[] result = response.as(User[].class);
assertEquals(result.length, 2);
}
دقت کنید که ما قبلا ایمیل را از Predicate خارج کرده بودیم پس این کوئری نادیده گرفته میشود و جوابی در بر نخواهد داشت