Reputation: 11888
I want to do a simple conditional JPA query to get a list of BankTransactions from the bankAccountNumber and branchCode.
My cases are
get("12345678","123") gets all the transactions for bank account 12345678 and branch 123
get(null,"123") gets all the transactions for all bank accounts and branch 123
get(null,null) gets all the transactions
I've written this code, but it seems really smelly since there is no initial value for BooleanExpression.
I think I am misunderstanding the API. How do I clean this up ?
(Am I misunderstanding the API ?)
public Page<BankTransactions> get(
@RequestParam(required = false) String bankAccountNumber,
@RequestParam(required = false) String branchCode,
Pageable pageable) {
QBankTransactions q = QBankTransactions.bankTransactions;
BooleanExpression expression = null;
if (bankAccountNumber != null) {
if (expression == null) {
expression = q.bankAccountNumber.eq(bankAccountNumber);;
} else {
expression.and(q.bankAccountNumber.eq(bankAccountNumber));
}
}
if (branchCode != null) {
if (expression == null) {
expression = q.branchCode.eq(branchCode);
} else {
expression.and(q.branchCode.eq(branchCode));
}
}
if (expression != null) {
Page<BankTransactions> response = repository.findAll(expression, pageable);
return response;
} else {
Page<BankTransactions> response = repository.findAll(pageable);
return response;
}
}
Upvotes: 1
Views: 651
Reputation: 377
This is my solution using QueryDslPredicateExecutor (which allows the execution of the Predicate) & QueryDslBindings (which allows path specific bindings - API).
So for example below if I tried looking up description of "FindMe" using "ind" or "Ind" it'll return the result in both instances correctly for "FindMe. Bindings won't be bound that are not found on the predicate from the HTTPRequest.
public interface BankTransactionsRepository extends PagingAndSortingRepository<BankTransactions, Long>,
QueryDslPredicateExecutor<BankTransactions>,
QuerydslBinderCustomizer<QBankTransactions> {
@Override
default public void customize(QuerydslBindings bindings,
QBankTransactions root) {
bindings.bind(root.description).first((path, value) -> path.containsIgnoreCase(value));
bindings.bind(root.template.code).first((path, value) -> path.containsIgnoreCase(value));
bindings.bind(root.status).first((path, value) -> path.containsIgnoreCase(value));
bindings.bind(root.processedDate).first((path, value) -> path.eq(value));
}
}
Upvotes: 1
Reputation: 324
Simple pass a predicate into the method parameter. More info.
public Page<BankTransactions> get(
@QuerydslPredicate(root = BankTransactions.class) Predicate predicate,
Pageable pageable, @RequestParam MultiValueMap<String, String> parameters) {
Page<BankTransactions> response = repository.findAll(predicate, pageable);
return response;
}
Upvotes: 1
Reputation: 11888
I really don't like this answer, but at least it makes my code look cleaner. I added helper methods (eq) for each data type.
A least now my code is one line per input discriminator.
public Page<BankTransactions> get(
@RequestParam(required = false) String bankAccountNumber,
@RequestParam(required = false) String branchCode,
Pageable pageable) {
QBankTransactions q = QBankTransactions.bankTransactions;
BooleanExpression expression = null;
expression = eq(bankAccountNumber, expression, q.bankAccountNumber);
expression = eq(branchCode, expression, q.branchCode);
if (expression != null) {
Page<BankTransactions> response = repository.findAll(expression, pageable);
return response;
} else {
Page<BankTransactions> response = repository.findAll(pageable);
return response;
}
}
private BooleanExpression eq(String inputString, BooleanExpression expression, StringPath path) {
if (inputString != null) {
if (expression == null) {
expression = path.eq(inputString);
} else {
expression.and(path.eq(inputString));
}
}
return expression;
}
private BooleanExpression eq(Long inputLong, BooleanExpression expression, NumberPath path) {
if (inputLong != null) {
if (expression == null) {
expression = path.eq(inputLong);
} else {
expression.and(path.eq(inputLong));
}
}
return expression;
}
Upvotes: 0