Spring-data, Oliver Gierke's excellent library, has something called a Specification (org.springframework.data.jpa.domain.Specification). With it you can generate several predicates to narrow your criteria for searching.
Can someone provide an example of using a Subquery from within a Specification?
I have an object graph and the search criteria can get pretty hairy. I would like to use a Specification to help with the narrowing of the search, but I need to use a Subquery to see if some of the sub-elements (within a collection) in the object graph meet the needs of my search.
Thanks in advance.
JPA 2.0 supports subqueries in WHERE and HAVING clauses. In those they can be used in many types of expressions, including EXISTS and IN.
In the first step, I instantiate a CriteriaQuery which returns Author entities. Then I call the subquery method on the CriteriaQuery to create a subquery that counts the Books written by the Author which is selected by the outer query. As you can see, I define the subquery in the same way as I create a CriteriaQuery.
Internally, Spring generates a JPQL query based on the method name, sets the provided method parameters as bind parameter values, executes the query and returns the result.
Querydsl is a framework that enables the construction of statically typed SQL-like queries through its fluent API. Spring Data modules offer integration with Querydsl through QuerydslPredicateExecutor .
String projectName = "project1";
List<Employee> result = employeeRepository.findAll(
new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Subquery<Employee> sq = query.subquery(Employee.class);
Root<Project> project = sq.from(Project.class);
Join<Project, Employee> sqEmp = project.join("employees");
sq.select(sqEmp).where(cb.equal(project.get("name"),
cb.parameter(String.class, projectName)));
return cb.in(root).value(sq);
}
}
);
is the equivalent of the following jpql query:
SELECT e FROM Employee e WHERE e IN (
SELECT emp FROM Project p JOIN p.employees emp WHERE p.name = :projectName
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With