问题:
Spring Data JPA 存储库支持使用固定、预定义的查询创建参数。但是,需要根据用户提供的字段动态生成具有任意 AND 子句的查询。这种方法扩展性很差,并且需要对每种可能的组合进行显式查询定义。
最佳方法:使用 Criteria API 的规范
Spring Data 提供了利用 Criteria API 构建灵活和动态的规范查询。通过使用 JpaSpecificationExecutor 扩展存储库接口,可以使用各种方法执行规范,包括 findAll。
规范接口:
public interface Specification<T> { Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder); }
示例实现:
public static Specification<Customer> isLongTermCustomer() { return new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder builder) { LocalDate date = new LocalDate().minusYears(2); return builder.lessThan(root.get('dateField'), date); } }; } public static Specification<Customer> hasSalesOfMoreThan(MontaryAmount value) { return new Specification<Customer>() { public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) { // build query here } }; }
用法示例:
List customers = customerRepository.findAll(isLongTermCustomer()); MonetaryAmount amount = new MonetaryAmount(200.0, Currencies.DOLLAR); List<Customer> customers = customerRepository.findAll( where(isLongTermCustomer()).or(hasSalesOfMoreThan(amount)));
复杂规范:
对于复杂规范,您可以在规范中定义自定义方法类:
public static Specification<WorkInProgress> findByCriteria(final SearchCriteria searchCriteria) { return new Specification<WorkInProgress>() { public Predicate toPredicate(Root<WorkInProgress> root, CriteriaQuery<?> query, CriteriaBuilder cb) { List<Predicate> predicates = new ArrayList<Predicate>(); // Add predicates based on search criteria return cb.and(predicates.toArray(new Predicate[] {})); } }; }
结论:
规范允许动态查询生成,而不需要显式查询定义。这种方法具有可伸缩性和可扩展性,简化了灵活且可定制的查询的创建。有关更多信息,请参阅 JPA 存储库文档。
以上是如何使用任意 AND 子句创建动态 Spring Data JPA 查询?的详细内容。更多信息请关注PHP中文网其他相关文章!