为 restful 链接 QueryDSL 的简单方法

Easy way of chaining QueryDSL for restful get

我想做一个简单的条件 JPA 查询,从 bankAccountNumberbranchCode.[=13= 获取 BankTransactions 列表]

我的案例是

  1. get("12345678","123") 获取银行账户 12345678 和分行的所有交易123

  2. get(null,"123") 获取所有银行账户和分行的所有交易 123

  3. get(null,null) 获取所有交易

我写了这段代码,但是看起来很臭,因为BooleanExpression没有初始值。

我想我误解了API。我该如何清理它?

(我是不是误解了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;
  }
}

我真的不喜欢这个答案,但至少它让我的代码看起来更清晰。我为每种数据类型添加了辅助方法 (eq)。

至少现在我的代码是每个输入鉴别器一行。

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;
}

简单地将谓词传递到方法参数中。 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;

}

这是我使用 QueryDslPredicateExecutor(允许执行谓词)和 QueryDslBindings(允许路径特定绑定 - API)的解决方案。

因此,例如下面的示例,如果我尝试使用 "ind" 或 "Ind" 查找 "FindMe" 的描述,它将 return 在两个实例中正确地找到“FindMe”的结果. 不会绑定未在 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));
  }    
}