二、JPA多条件查询
我们依然使用昨天的Repository 但是仅仅继承JpaRepository是不够的,若要完成复杂查询则需要继承JpaSpecification<Person> “<>”里面存放的是该接口需要操作的实体类对象,我们仍以昨天的Person类对象为例。
@Repositorypublic interface PersonRepository extends JpaRepository<Person,Long>, JpaSpecificationExecutor<Person> {}
实现的步骤首先是创建一个specification 对象,然后实现里面的toPredicate()方法,然后可以使用if语句动态的构建查询参数,前端传入相应的参数,就拼接对应的查询语句,该字段为null则不拼接对应的查询语句,非常的方便灵活。拼接好相应的查询语句后,再利用and连接构建一个predicate 对象。最后传入specification、pageable等参数,使用repository已经帮我们实现的findAll(specification, pageable)方法实现分页(排序)的多条件查询。该方法将返回一个page对象,里面包含了分页数据以及分页信息。
构建查询语句时,其中的api设计和SQL本来的原意很相近,容易理解。具体相关的api都以注释的形式放在代码中。这些非常直观的api可以帮助我们拼接成丰富多彩的查询语句,避免我们手动去写原生的SQL语句。
/*** todo spring data jpa 使用specification 进行查询 3-11* 十分实用和好用** @param query* @return*/public Page<Person> queryPersonsByLamdaConditions(PersonQuery query) {// List<Sort.Order> orders = new ArrayList<>();// Sort.Order order1= new Sort.Order(Sort.Direction.ASC,"createTime");// Sort.Order order2= new Sort.Order(Sort.Direction.ASC,"personType");// orders.add(order2);// orders.add(order1);// new Sort(orders)// 多个字段进行排序Sort sort = new Sort(Sort.Direction.DESC, "personType").and(new Sort(Sort.Direction.ASC, "createTime"));Pageable pageable = PageRequest.of(query.getPage() - 1, query.getPageSize(), sort);// 先创建一个说明书, 借助这个说明书进行查询Specification<Person> specification = new Specification<Person>() {@Overridepublic Predicate toPredicate(Root<Person> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {// 然后再创建一个查询预测条件的数组List<Predicate> list = new ArrayList<>();// 模糊查询 likeif (StringUtils.isNotBlank(query.getUserName())) {list.add(criteriaBuilder.like(root.get("userName"), query.getUserName()));}// 等于 equalif (query.getAge() != null) {list.add(criteriaBuilder.equal(root.get("age"), query.getAge()));}// where in list集合if (CollectionUtils.isNotEmpty(query.getUnitIds())) {list.add(criteriaBuilder.in(root.get("unitId")).value(query.getUnitIds()));}if (Objects.nonNull(query.getCreateTime())) {// 大于等于// list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), query.getCreateTime()));// 大于// list.add(criteriaBuilder.greaterThan(root.get("createTime"), query.getCreateTime()));// 小于等于// list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime"), query.getCreateTime()));// 小于list.add(criteriaBuilder.lessThan(root.get("createTime"), query.getCreateTime()));}// 介于二者之间的if (Objects.nonNull(query.getStartTime()) && Objects.nonNull(query.getEndTime())) {list.add(criteriaBuilder.between(root.get("createTime"), query.getStartTime(), query.getEndTime()));}Predicate[] predicates = new Predicate[list.size()];// 将其转换成predicate数组return criteriaBuilder.and(list.toArray(predicates));}};Page<Person> page = personRepository.findAll(specification, pageable);List<Person> personEntities = page.getContent();// 此处可以将 personEntities 可以再转换为vo// List<PersonVo> personVoList = MapperUtil.mapperObjectList(PersonVo.class, personEntities);// 再新构建一个page页面return new PageImpl<>(personEntities, pageable, page.getTotalElements());}
三、小结
面对一些多条件复杂查询,JPA内置方法以及通过方法名构建的简单方法已经不能满足我们的需求,这时候需要在repository中继承JpaSpecificationExecutor接口,然后创建一个specification对象和pageable对象,调用findAll(specification,pageable)方法完成多条件的查询任务。
文章转载自DevHome,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




