栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Data JPA实现动态条件与范围查询实例代码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Data JPA实现动态条件与范围查询实例代码

Spring Data JPA为我们提供了Query With Example来实现动态条件查询,当查询条件为空的时候,我们不用做大量的条件判断。但是Query With Example却不支持范围查询(包括日期范围,数值范围查询),本文通过Specification实现了既支持动态条件查询又支持范围查询的方法。

1 实现方式

1.1 范围对象Range定义

import java.io.Serializable;


public class Range implements Serializable {
  private static final long serialVersionUID = 1L;

  private String field;
  private Comparable from;
  private Comparable to;
  private Boolean includeNull;


  public Range(String field) {
    this.field = field;
  }


  public Range(String field, Comparable from, Comparable to) {
    this.field = field;
    this.from = from;
    this.to = to;
  }

  public Range(String field, Comparable from, Comparable to, Boolean includeNull) {
    this.field = field;
    this.from = from;
    this.to = to;
    this.includeNull = includeNull;
  }


  public Range(Range other) {
    this.field = other.getField();
    this.from = other.getFrom();
    this.to = other.getTo();
    this.includeNull = other.getIncludeNull();
  }

  public String getField() {
    return field;
  }

  public Comparable getFrom() {
    return from;
  }


  public void setFrom(Comparable from) {
    this.from = from;
  }

  public boolean isFromSet() {
    return getFrom() != null;
  }


  public Comparable getTo() {
    return to;
  }

  public void setTo(Comparable to) {
    this.to = to;
  }

  public boolean isToSet() {
    return getTo() != null;
  }

  public void setIncludeNull(boolean includeNull) {
    this.includeNull = includeNull;
  }

  public Boolean getIncludeNull() {
    return includeNull;
  }

  public boolean isIncludeNullSet() {
    return includeNull != null;
  }

  public boolean isBetween() {
    return isFromSet() && isToSet();
  }

  public boolean isSet() {
    return isFromSet() || isToSet() || isIncludeNullSet();
  }

  public boolean isValid() {
    if (isBetween()) {
      return getFrom().compareTo(getTo()) <= 0;
    }

    return true;
  }
}

1.2 example的Specification

import org.springframework.data.domain.Example;
import org.springframework.data.jpa.convert.QueryByExamplePredicateBuilder;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.Assert;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;


public class ByExampleSpecification implements Specification {
  private final Example example;

  public ByExampleSpecification(Example example) {

    Assert.notNull(example, "Example must not be null!");
    this.example = example;
  }


  @Override
  public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
    return QueryByExamplePredicateBuilder.getPredicate(root, cb, example);
  }
}

1.3 Range的Specification

import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;

import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Lists.newArrayList;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;


public class ByRangeSpecification implements Specification {
  private final List> ranges;

  public ByRangeSpecification(List> ranges) {
    this.ranges = ranges;
  }

  @Override
  public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder builder) {
    List predicates = newArrayList();

    for (Range range : ranges) {
      if (range.isSet()) {
 Predicate rangePredicate = buildRangePredicate(range, root, builder);

 if (rangePredicate != null) {
   if (!range.isIncludeNullSet() || range.getIncludeNull() == FALSE) {
     predicates.add(rangePredicate);
   } else {
     predicates.add(builder.or(rangePredicate, builder.isNull(root.get(range.getField()))));
   }
 }

 if (TRUE == range.getIncludeNull()) {
   predicates.add(builder.isNull(root.get(range.getField())));
 } else if (FALSE == range.getIncludeNull()) {
   predicates.add(builder.isNotNull(root.get(range.getField())));
 }
      }
    }
    return predicates.isEmpty() ? builder.conjunction() : builder.and(toArray(predicates, Predicate.class));
  }

  private Predicate buildRangePredicate(Range range, Root root, CriteriaBuilder builder) {
    if (range.isBetween()) {
      return builder.between(root.get(range.getField()), range.getFrom(), range.getTo());
    } else if (range.isFromSet()) {
      return builder.greaterThanOrEqualTo(root.get(range.getField()), range.getFrom());
    } else if (range.isToSet()) {
      return builder.lessThanOrEqualTo(root.get(range.getField()), range.getTo());
    }
    return null;
  }

}

1.4 自定义Repository与实现

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;
import java.util.List;

@NoRepositoryBean
public interface WiselyRepository extends JpaRepository {


 Page queryByExampleWithRange(Example example,List> ranges, Pageable pageable);

}
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import java.io.Serializable;
import java.util.List;

import static org.springframework.data.jpa.domain.Specifications.where;


public class WiselyRepositoryImpl extends SimpleJpaRepository implements
    WiselyRepository {
  private final EntityManager entityManager;

  public WiselyRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    this.entityManager = entityManager;
  }



  @Override
  public Page queryByExampleWithRange(Example example, List> ranges, Pageable pageable) {
    Specification byExample = new ByExampleSpecification<>(example);
    Specification byRanges = new ByRangeSpecification<>(ranges);
    return findAll(where(byExample).and(byRanges),pageable);
  }
}

2 使用方式

2.1 开启支持

通过@EnableJpaRepositories(repositorybaseClass = WiselyRepositoryImpl.class)开启对定义功能的支持。

2.2 示例

实体类

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  private Integer height;
  @DateTimeFormat(pattern = "yyyy-MM-dd")
  private Date birthday;
}

PersonRepository

public interface PersonRepository extends WiselyRepository {
}

测试控制器

@RestController
@RequestMapping("/people")
public class PersonController {

  @Autowired
  PersonRepository personRepository;

  @PostMapping
  public ResponseEntity save(@RequestBody Person person){
    Person p = personRepository.save(person);
    return new ResponseEntity(p, HttpStatus.CREATED);
  }


  @GetMapping
  public ResponseEntity> query(Person person,
  @DateTimeFormat(pattern = "yyyy-MM-dd")Date startDate,
  @DateTimeFormat(pattern = "yyyy-MM-dd")Date endDate,
  Integer startHeight,
  Integer endHeight,
  Pageable pageable){
    Example personExample = Example.of(person);

    List> ranges = newArrayList();
    Range birthRange = new Range("birthday",startDate,endDate);
    Range heightRange = new Range("height",startHeight,endHeight);
    ranges.add(birthRange);
    ranges.add(heightRange);

    Page page = personRepository.queryByExampleWithRange(personExample,ranges,pageable);

    return new ResponseEntity>(page,HttpStatus.OK);

  }
}

源码地址:https://github.com/wiselyman/query_with_example_and_range

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/145493.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号