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

网友投稿 786 2023-05-05


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 froOGOTjUm, 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;

/**

* Created by wangyunfei on 2017/6/6.

*/

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;

/**

* Created by wangyunfei on 2017/6/6.

*/

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java实现大数运算的实例代码
下一篇:微信开发者工具mock导入数据(微信开发者工具导入模板)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~