In the last tutorial we went through default Querydsl bindings. In this tutorial we will learn how to use customized ones.
There are two ways to customize the Querydsl bindings:
- By using
@QuerydslPredicate annotation with Predicate parameter in controller method and assigning its attribute bindings to a class implementing QuerydslBinderCustomizer .
- By implementing
QuerydslBinderCustomizer in our repository interface, and overriding its method customize() as Java 8 default method.
Example
JPA Entity
@Entity
public class Employee {
private @Id
@GeneratedValue
Long id;
private String name;
private String dept;
private int salary;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date dateOfBirth;
.............
}
In above entity we are using Jackson annotation @JsonFormat to serialize java.sql.Date as formatted string in the web response, by default the date is serialized as number of seconds since epoch.
Implementing QuerydslBinderCustomizer
package com.logicbig.example;
import com.querydsl.core.types.dsl.NumberExpression;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long>,
QuerydslPredicateExecutor<Employee>, QuerydslBinderCustomizer<QEmployee> {
@Override
default void customize(QuerydslBindings bindings, QEmployee root) {
bindings.bind(root.salary)
.first(NumberExpression::goe);
bindings.bind(root.dateOfBirth)
.all((path, value) -> {
List<? extends Date> dates = new ArrayList<>(value);
if (dates.size() == 1) {
return Optional.of(path.eq(dates.get(0)));
} else {
Date from = dates.get(0);
Date to = dates.get(1);
return Optional.of(path.between(from, to));
}
});
}
}
In above example, the first custom binding is using
QuerydslBindings.first() method to bind the first value in the query string for the target path (employee.salary). If for the same property, there are more than one values in the requested query string then the rest are ignored. Also we are applying 'goe' (greater than or equals) predicate for the salary.
The method
QuerydslBindings.all() is used to bind all values in the query string for the target path. In above example we are using only first and second values for 'dateOfBirth' property to apply 'between' criteria.
MVC controller
@RestController
public class EmployeeController {
@Autowired
private EmployeeRepository repository;
@GetMapping("/employees")
public List<Employee> getEmployees(Predicate predicate) {
Iterable<Employee> iterable = repository.findAll(predicate);
List<Employee> employees = StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
return employees;
}
}
Running
To try examples, run embedded tomcat (configured in pom.xml of example project below):
mvn tomcat7:run-war
Output
http://localhost:8080/employees (without any query string)
http://localhost:8080/employees?salary=6000 (returns employees with salaries greater then 6000 inclusively)
http://localhost:8080/employees?dateOfBirth=1999-10-19&dateOfBirth=2005-01-01 (returns employees only within the provided range of date of births)
We can still use the default bindings along with the customized one:
http://localhost:8080/employees?salary=6000&dept=IT
Example ProjectDependencies and Technologies Used: - spring-data-jpa 2.0.7.RELEASE: Spring Data module for JPA repositories.
Uses org.springframework:spring-context version 5.0.6.RELEASE - spring-webmvc 5.0.6.RELEASE: Spring Web MVC.
- querydsl-apt 4.2.1: APT based Source code generation for Querydsl.
- querydsl-jpa 4.2.1: JPA support for Querydsl.
- jackson-databind 2.9.5: General data-binding functionality for Jackson: works on core streaming API.
- javax.servlet-api 3.0.1 Java Servlet API
- hibernate-core 5.3.1.Final: Hibernate's core ORM functionality.
Implements javax.persistence:javax.persistence-api version 2.2 - h2 1.4.197: H2 Database Engine.
- JDK 1.8
- Maven 3.3.9
|