当前位置: 首页 > 知识库问答 >
问题:

带有任意AND子句的动态spring数据jpa存储库查询

龚征
2023-03-14

我使用的是Spring data jpa存储库,需要提供不同字段的搜索特性。在搜索前输入字段是可选的。我有5个字段,即EmployeeEnumberName已婚ProfessionDateOfborn
这里我只需要按用户查询给定的值,其他字段应该忽略。ex,

Input : EmployeeNumber: ,Name:St,Married: ,Professsion:IT,DateOfBirth: 
Query : Select * from Employee e where Name like 'St%' and Profession like 'IT%';  

Input : EmployeeNumber:10,Name: ,Married: ,Professsion:IT,DateOfBirth:
Query : Select * from Employee e where EmployeeNumber like '10%' and Profession like 'IT%';  

所以这里我们要考虑输入和查询的值。在这种情况下,Spring data有本文中提到的限制(不可伸缩,所有可能的查询都应该编写)我使用querydsl,但问题仍然存在,因为null字段应该被忽略,几乎所有可能的查询都需要开发。在这个案例中,31查询。如果搜索字段为6、7、8...怎么办??

用可选字段实现搜索选项的最佳方法是什么?

共有1个答案

潘学民
2023-03-14

您可以使用Spring-data提供的开箱即用的规范。并且能够使用criteria API编程构建查询。为了支持规范,您可以使用JpaSpecificationExecutor接口扩展存储库接口

public interface CustomerRepository extends SimpleJpaRepository<T, ID>, JpaSpecificationExecutor {

}

附加接口(JpaSpecificationExecutor)携带的方法允许您以各种方式执行规范。

例如,findAll方法将返回与规范匹配的所有实体:

List<T> findAll(Specification<T> spec);
public interface Specification<T> {
     Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
            CriteriaBuilder builder);
}
public class CustomerSpecs {
    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());

您还可以结合规范示例2.17。组合规格

    MonetaryAmount amount = new MonetaryAmount(200.0, Currencies.DOLLAR);
    List<Customer> customers = customerRepository.findAll(
        where(isLongTermCustomer()).or(hasSalesOfMoreThan(amount)));

正如您所看到的,Specifications提供了一些粘合代码的方法来链接和组合Specifications。因此,扩展您的数据访问层仅仅是创建新的规范实现并将它们与现有的规范实现结合起来的问题。

您可以创建复杂的规范,下面是一个示例

public class WorkInProgressSpecification {
    public static Specification<WorkInProgress> findByCriteria(final SearchCriteria searchCriteria) {

        return new Specification<WorkInProgress>() {

            @Override
            public Predicate toPredicate(
                Root<WorkInProgress> root,
                CriteriaQuery<?> query, CriteriaBuilder cb) {

                List<Predicate> predicates = new ArrayList<Predicate>();

                if (searchCriteria.getView() != null && !searchCriteria.getView().isEmpty()) {
                    predicates.add(cb.equal(root.get("viewType"), searchCriteria.getView()));
                }
                if (searchCriteria.getFeature() != null && !searchCriteria.getFeature().isEmpty()) {
                    predicates.add(cb.equal(root.get("title"), searchCriteria.getFeature()));
                }
                if (searchCriteria.getEpic() != null && !searchCriteria.getEpic().isEmpty()) {
                    predicates.add(cb.equal(root.get("epic"), searchCriteria.getEpic()));
                }
                if (searchCriteria.getPerformingGroup() != null && !searchCriteria.getPerformingGroup().isEmpty()) {
                    predicates.add(cb.equal(root.get("performingGroup"), searchCriteria.getPerformingGroup()));
                }
                if (searchCriteria.getPlannedStartDate() != null) {
                    System.out.println("searchCriteria.getPlannedStartDate():" + searchCriteria.getPlannedStartDate());
                    predicates.add(cb.greaterThanOrEqualTo(root.<Date>get("plndStartDate"), searchCriteria.getPlannedStartDate()));
                }
                if (searchCriteria.getPlannedCompletionDate() != null) {
                    predicates.add(cb.lessThanOrEqualTo(root.<Date>get("plndComplDate"), searchCriteria.getPlannedCompletionDate()));
                }
                if (searchCriteria.getTeam() != null && !searchCriteria.getTeam().isEmpty()) {
                    predicates.add(cb.equal(root.get("agileTeam"), searchCriteria.getTeam()));
                }

                return cb.and(predicates.toArray(new Predicate[] {}));
            }
        };
    }
}

以下是JPA资源库文档

 类似资料:
  • 问题内容: 我正在使用,要求提供具有不同字段的搜索功能。搜索之前输入的字段是optional.I有5场说。 在这里我只需要查询用户给定的值,其他字段应该被忽略。 因此,这里我们考虑输入的值和进行查询。在这种情况下,Spring数据是具有限制中提到的这篇文章(不可扩展,所有可能出现的问题,应书面)我使用的,但仍然存在问题的领域应该被忽视,需要开发的几乎所有可能出现的问题。在这。如果搜索字段是? 用可

  • 问题内容: 我正在使用,要求提供具有不同字段的搜索功能。搜索之前输入的字段是有5场说。 在这里我只需要查询用户给定的值,其他字段应该被忽略。 因此,这里我们考虑输入的值和进行查询。在这种情况下,Spring数据是具有限制中提到的这篇文章(不可扩展,所有可能出现的问题,应书面)我使用的,但仍然存在问题的null领域应该被忽视,需要开发的几乎所有可能出现的问题。在这。如果搜索字段是? 用可选字段实现搜

  • 目前我一直在使用以下Spring JPA存储库自定义查询, 我需要修改这个查询时,筛选文本将是逗号分隔的值。但按照以下方式,它将是一个动态查询,我如何执行它。 我需要构建动态查询,

  • 我有一个简单的查询如下“select * from USERS”。我还使用Pageable来启用分页。 此查询可能具有基于给定参数是否为 null 的可选谓词。 例如,如果给定了“code”参数且该参数不为空,则查询变为“select * from USERS where code =:code”; 据我所知,我不能使用@Query注释来实现这一点。我可以实现一个定制的存储库,并使用EntityM

  • 我尝试过用Spring Boot实现JPA存储库,它工作得很好。现在,如果我尝试在使用@query注释扩展JpaRepository的接口中实现自定义查询,它可以很好地返回bean列表(使用NamedQuery)。现在,当我尝试为自定义方法/查询使用分页时,它不起作用。 代码: 控制器: 服务 异常:java.lang.IllegalArgumentException:为TypedQuery[ja