黑马程序员技术交流社区

标题: 【石家庄校区】Specification的使用 [打印本页]

作者: jgz2121    时间: 2017-11-28 19:45
标题: 【石家庄校区】Specification的使用
本帖最后由 小石姐姐 于 2017-11-29 16:33 编辑

spring data jpa 通过创建方法名来做查询,只能做简单的查询,那如果我们要做复杂一些的查询呢,多条件分页怎么办,这里,spring data jpa为我们提供了JpaSpecificationExecutor接口,只要简单实现toPredicate方法就可以实现复杂的查询
1.首先让我们的接口继承于JpaSpecificationExecutor
public interface TaskDao extends JpaSpecificationExecutor<Task>{

}
2.JpaSpecificationExecutor提供了以下接口
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);
}
其中Specification就是需要我们传进去的参数,它是一个接口
public interface Specification<T> {

    Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}
3.通过重写toPredicate方法,返回一个查询 Predicate,spring data jpa会帮我们进行查询。

具体Action代码:

        // 分页查询
        @Action(value = "courier_pageQuery", results = { @Result(name = "success", type = "json") })
        public String pageQuery() {

                // 在进行有条件的查询时,需要使用Specification接口
                Specification<Courier> specification = new Specification<Courier>() {
                        /**
                         *  构造条件查询方法,如果方法返回的是null,代表无条件查询 Root : 获取条件表达式(其实是查询的主表) , name=? , age = ?
                         *  CriteriaQuery : 构造简单查询条件返回,提供where
                         *  CriteriaBuilder : 构造Predicate对象, 条件对象, 构造复杂查询结果
                         */
                        @Override
                        public Predicate toPredicate(Root<Courier> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                                // 因为并不知道是否所有条件都填写
                                List<Predicate> list = new ArrayList<>();
                                
                                // 表单查询(查询当前对象对应的数据表)
                                // 进行快递员工号查询,判断是否为空
                                if (StringUtils.isNotBlank(courier.getCourierNum())) {
                                        // 第一个参数是表达式,获取数据库中对应字段的内容. 第二个参数是前台传递过来的通过courier封装的数据
                                        Predicate p1 = cb.equal(root.get("courierNum").as(String.class), courier.getCourierNum());
                                        list.add(p1);
                                }
                                // 进行公司查询,模糊查询
                                if (StringUtils.isNotBlank(courier.getCompany())) {
                                        Predicate p2 = cb.like(root.get("company").as(String.class), "%" + courier.getCompany() + "%");
                                        list.add(p2);
                                }

                                // 进行快递员类型查询,等值查询
                                if (StringUtils.isNotBlank(courier.getType())) {
                                        Predicate p3 = cb.equal(root.get("type").as(String.class), courier.getType());
                                        list.add(p3);
                                }
                                // 收派标准查询,涉及多表复杂查询 模糊查询
                                if (courier.getStandard() != null && StringUtils.isNotBlank(courier.getStandard().getName())) {
                                        // 使用root 主表 关联 从表 standard
                                        Join<Object, Object> standardRoot = root.join("standard", JoinType.INNER);// 默认是内连接
                                        Predicate p4 = cb.like(standardRoot.get("name").as(String.class),courier.getStandard().getName());
                                        list.add(p4);
                                }
                                // 将所有的条件组装
                                return cb.and(list.toArray(new Predicate[0]));
                        }
                };

                Pageable pageable = new PageRequest(page - 1, rows);

                Page<Courier> pageData = courierService.pageQuery(specification,pageable);

                PageBean<Courier> page = new PageBean<>();
                page.setTotal(pageData.getTotalElements());
                page.setRows(pageData.getContent());

                ActionContext.getContext().getValueStack().push(page);

                return SUCCESS;
        }

作者: 小石姐姐    时间: 2017-11-29 16:33





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2