JpaSpecificationExecutor的认识

7 篇文章 0 订阅

4.JpaSpecificationExecutor的认识
Specification:[ˌspɛsəfɪˈkeʃən]
Executor:[ɪgˈzekjətə®]
Criteria:美 [kraɪˈtɪrɪə]
JpaSpecificationExecutor(JPA规则执行者)是JPA2.0提供的Criteria API的使用封装,可以用于动态生成Query来满足我们业务中的各种复杂场景。
Spring Data JPA为我们提供了JpaSpecificationExecutor接口,只要简单实现toPredicate方法就可以实现复杂的查询。

咱们先来看一下这个接口的方法(大家注意一下,所以查询都要求传入一个Specification对象):
SimpleJpaRepository也实现了这个接口

package org.springframework.data.jpa.repository;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

public interface JpaSpecificationExecutor<T> {
   T findOne(Specification<T> spec);
   List<T> findAll(Specification<T> spec);
   Page<T> findAll(Specification<T> spec, Pageable pageable);
   List<T> findAll(Specification<T> spec, Sort sort);
   long count(Specification<T> spec);
}

我们要使用这个接口中的方法,首先让我们的接口也去继承这个接口

public interface EmployeeRepository extends JpaRepository<Employee,Long>,JpaSpecificationExecutor<Employee> {
4.1.单个条件的查询
@Test
public void testFind() {
    /**
*官方解释:
     * Root<T> root:代表了可以查询和操作的实体对象的根,
     *              可以通过它的 Path<Y> get(String attributeName); 这个方法拿到我们要操作的字段
     *              注意:只可以拿到对应的T的字段(Employee)
     * CriteriaQuery<?> query:代表一个specific的顶层查询对象
     *              包含查询的各个部分,比如select,from,where,group by ,order by 等
     *              简单理解 就是它提供 了查询ROOT的方法(where,select,having)
     * CriteriaBuilder cb:用来构建CriteriaQuery的构建器对象(相当于条件或者说条件组合)
     *              构造好后以Predicate的形式返回
     */
/**
* 非官方理解:
 * 查询的时候就需要给一个标准(规范)
 *  -》 根据规范(这个规范我们可以先简单理解为查询的条件)进行查询
 *
 *      Root:查询哪个表(定位到表和字段-> 用于拿到表中的字段)
 *            可以查询和操作的实体的根
 *              Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似
 *             Root<Employee> 相当于 from Employee
 *             Root<Product> 相当于  from Product
 *      CriteriaQuery:查询哪些字段,排序是什么(主要是把多个查询的条件连系起来)
 *      CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么方式
 *                      主要判断关系(和这个字段是相等,大于,小于like等)
 *      Predicate(Expression):单独每一条查询条件的详细描述 整个 where xxx=xx and yyy=yy ...
 */
    List<Employee> emps = employeeRepository.findAll(
            new Specification<Employee>() {
                @Override
                public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    Path path = root.get("username");//拿到要做查询的字段
                    Predicate p = cb.like(path, "%1%");//like代表做模糊查询,后面就是它的条件值
                    return p;
                }
            }
    );
    for (Employee emp : emps) {
        System.out.println(emp);
    }
}

4.2.多个条件查询

@Test
public void testFind02() {
    Specification spec = new Specification<Employee>() {
        @Override
        public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
            //加上第一个条件: username like '%1%'
            Path path1 = root.get("username");
            Predicate p1 = cb.like(path1, "%1%");
            //加上第二个条件: email like '%2%'
            Path path2 = root.get("email");
            Predicate p2 = cb.like(path2,"%2%");
            //加上第二个条件: age < 20
            Path path3 = root.get("age");
            Predicate p3 = cb.lt(path3, 20);
           //下面是加上or的条件的方案
           //Predicate p3 = cb.or(p1,p2);

            //把两个查询条件放到query对象中去(条件使用where)
            CriteriaQuery where = query.where(p1, p2, p3);
            //返回查询条件
            return where.getRestriction();
        }
    };

    List<Employee> emps = employeeRepository.findAll(spec);
    for (Employee emp : emps) {
        System.out.println(emp);
    }

}

4.3.条件查询+分页排序
@Test
public void testFind03() {
    Specification spec = new Specification<Employee>() {
        @Override
        public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
            //加上条件: username like '%1%'
            Path path1 = root.get("username");
            Predicate p1 = cb.and(cb.like(path1, "%1%"));
            //把两个查询条件放到query对象中去(条件使用where)
            CriteriaQuery where = query.where(p1);
            //返回查询条件
            return where.getRestriction();
        }
    };

    //排序 :第一个参数是排序的规则(DESC/ASC)  后面参数是排序的字符
    Sort sort = new Sort(Sort.Direction.DESC,"username");
    Pageable pageable = new PageRequest(0, 10,sort);

    Page<Employee> page = employeeRepository.findAll(spec, pageable);
    for (Employee emp : page) {
        System.out.println(emp);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值