Spring Data Jpa-Criteria构建查询

377 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情

JpaSpecificationExecutor简介

spring data jpa中负责jpa查询的接口,封装了常用的基于对象查询的各种方法,与第一篇中介绍的几种查询方式相比最大优势是是可以动态指定查询条件,但是查询结果目测只能以实体进行封装。即Criteria构建查询条件。

接口说明

  • JpaSpecificationExecutor接口说明 |接口名称|说明| |-|-| |Optional findOne(@Nullable Specification spec);|查询一个实体| |List findAll(@Nullable Specification spec);|指定查询条件查询| |Page findAll(@Nullable Specification spec, Pageable pageable);|分页查询| |List findAll(@Nullable Specification spec, Sort sort);|排序查询| |long count(@Nullable Specification spec);|查询总数|

通过上面的接口我们会发现一个很诡异的问题,就是分页查询和排序好像不能同时存在,其实Pageable是有多个实现的,除了通常只有关于分页的查询之外还有一个PageRequest,这个类可以支持排序和分页共存。使用方法为PageRequest.of(int page, int size, Sort sort);

  • Specification接口说明 这个接口下包含一个接口用于构建查询条件
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);

还有4个静态方法,静态方法分别是where,not,and,or参数为Specification.当查询条件可复用时可专门构建一个产生查询条件的工厂,并在查询时使用静态方法进行连接。

JPA查询说明

  • 参数说明: 参数Root:查询根,join ,fetch深度获取,当属性为集合时使用 参数CriteriaQuery:查询主体,可增加groupBy,distinct,having, 参数CriteriaBuilder:构建查询条件及一些基础函数 返回值Predicate:条件组合

  • 例子

return this.findAll(new Specification<FileInfo>() {
        @Nullable
        @Override
        public Predicate toPredicate(Root<FileInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                criteriaQuery.distinct(true);
                criteriaQuery.multiselect(
                                criteriaBuilder.max(root.get("id")),
                                root.get("createdDate"),
                                root.get("fileName"),
                                root.get("url")
                );
                criteriaQuery.groupBy(root.get("createdDate"),
                                root.get("fileName"),
                                root.get("url"));
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(root.get("relationId").as(Long.class).in(ids));
                predicates.add(criteriaBuilder.equal(root.get("fileTag"), fileInfo.getChildFieTag()));
                Predicate condition = criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
                return condition;
        }
}, PageRequest.of(1,10,Sort.by("code").ascending()));

本来想写一些具体的例子,发现一个大神整理的jpa api用法汇总,就不献丑了。

其他

  • spirng boot jpa中获取EntityManager,获取之后可以在service中使用原生jpa代码构建jpql
@Autowired
 private JpaContext jpaContext;
public EntityManager getEm(){
  return jpaContext.getEntityManagerByManagedType(实体类.class);
 }
  • 简化jpa语法的工具包,有兴趣可以研究下
    1. QueryDSL介绍官网,官方支持功能强大,包也大。。
    2. jpa-spec介绍github,大神写的工具包,包小,简化构建Predicate 方法。

参考资料

www.baeldung.com/rest-api-se…

lufficc.com/blog/spring…

www.cnblogs.com/xingqi/p/39…