I am using Spring Data JPA and QueryDsl. I have no problem explicitly constructing search predicates and passing them to the repository methods. However, I like the idea of using the @QuerydslPredicate annotation on a web/REST controller's method argument when the queried entities have more than a few properties, and I want the flexibility of filtering the search by any of them. So, something like this, generally, works very well:
@GetMapping("/accounts/summaries")
public PageDto<AccountSummaryDto> getAccountSummaries(@QuerydslPredicate(root = AccountSummary.class) Predicate accountSearchPredicate,
@RequestParam(name = "pageIndex", defaultValue = "0") int pageIndex,
@RequestParam(name = "pageSize", defaultValue = "25") int pageSize,
@RequestParam(name = "sortBy", defaultValue = "id") String sortBy,
@RequestParam(name = "sortOrder", defaultValue = "desc") String sortOrder) {
// delegating to web-agnostic service that:
// - creates Pageable pageRequest,
// - calls accountSummaryRepository.findAll(predicate, pageRequest),
// - constructs custom PageDto wrapper, etc.
return accountService.retrieveAccountSummaries(accountSearchPredicate, pageIndex, pageSize, sortBy, sortOrder);
}
My Spring Data JPA repository interface I have something like this:
public interface AccountSummarySearchRepository
extends JpaRepository<AccountSummary, Integer>, QuerydslPredicateExecutor<AccountSummary>, QuerydslBinderCustomizer<QAccountSummary > {
@Override
default void customize(QuerydslBindings bindings, QAccountSummary acctSummary) {
bindings.bind(acctSummary.customer.firstName).first((path, value) -> path.isNull().or(path.startsWithIgnoreCase(value))) ;
bindings.bind(acctSummary.customer.lastName).first((path, value) -> path.isNull().or(path.startsWithIgnoreCase(value))) ;
// etc.
// default binding for String properties to be case insensitive "contains" match
bindings.bind(String.class).first(
(StringPath path, String value) -> path.isNull().or(path.containsIgnoreCase(value)));
}
Now... I what if want to ONLY retrieve the entities for those accounts where property deleted is set to false - without forcing the client to pass that as a query parameter? Similarly, I may want to set other default lookup values dynamically for each query. For example, I may want to "retrieve only those accounts where assignedTo == [current user ID available on a ThreadLocal]... Is there a simple way to set such "bindings" or infuse the auto-populated (via the @QuerydslPredicate annotation) incoming predicate with any additional implicit/default criteria that are not explicitly passed in the web request? I must be missing something very simple, right? There has to be a way. Unfortunately, there seem to be no comprehensive documentation for Spring QueryDsl support - other than some very simplistic examples.
By the time the search predicate arrives at the controller method, it is already processed by the customizer and populated with the property criteria that were passed to the endpoint as request params. I am trying to figure out the way to tap into the framework flow and make sure that the predicate is constructed as if the deleted=false (and, perhaps, other criteria) were passed among the request parameters.
Thanks for your help!
Aucun commentaire:
Enregistrer un commentaire