Spring Data JPA 동적 조건 및 범위 조회 인 스 턴 스 코드 구현
Spring Data JPA
은 우리 에 게Query With Example
동적 조건 조 회 를 실현 하도록 제공 했다.조회 조건 이 비어 있 을 때 우 리 는 대량의 조건 판단 을 할 필요 가 없다.그러나Query With Example
범위 조회(날짜 범위,수치 범위 조회 포함)를 지원 하지 않 고 본 고 는Specification
를 통 해 동적 조건 조회 와 범위 조 회 를 지원 하 는 방법 을 실현 했다.1 실현 방식
1.1 범위 대상 범위 정의
import java.io.Serializable;
public class Range<E> 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<E> 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<T> implements Specification<T> {
private final Example<T> example;
public ByExampleSpecification(Example<T> example) {
Assert.notNull(example, "Example must not be null!");
this.example = example;
}
@Override
public Predicate toPredicate(Root<T> 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<T> implements Specification<T> {
private final List<Range<T>> ranges;
public ByRangeSpecification(List<Range<T>> ranges) {
this.ranges = ranges;
}
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = newArrayList();
for (Range<T> 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<T> range, Root<T> 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<E, PK extends Serializable> extends JpaRepository<E, PK> {
Page<E> queryByExampleWithRange(Example example,List<Range<E>> 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<E, PK extends Serializable> extends SimpleJpaRepository<E, PK> implements
WiselyRepository<E, PK> {
private final EntityManager entityManager;
public WiselyRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
}
@Override
public Page<E> queryByExampleWithRange(Example example, List<Range<E>> ranges, Pageable pageable) {
Specification<E> byExample = new ByExampleSpecification<>(example);
Specification<E> 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<Person,Long> {
}
테스트 컨트롤 러
@RestController
@RequestMapping("/people")
public class PersonController {
@Autowired
PersonRepository personRepository;
@PostMapping
public ResponseEntity<Person> save(@RequestBody Person person){
Person p = personRepository.save(person);
return new ResponseEntity<Person>(p, HttpStatus.CREATED);
}
@GetMapping
public ResponseEntity<Page<Person>> query(Person person,
@DateTimeFormat(pattern = "yyyy-MM-dd")Date startDate,
@DateTimeFormat(pattern = "yyyy-MM-dd")Date endDate,
Integer startHeight,
Integer endHeight,
Pageable pageable){
Example<Person> personExample = Example.of(person);
List<Range<Person>> ranges = newArrayList();
Range<Person> birthRange = new Range<Person>("birthday",startDate,endDate);
Range<Person> heightRange = new Range<Person>("height",startHeight,endHeight);
ranges.add(birthRange);
ranges.add(heightRange);
Page<Person> page = personRepository.queryByExampleWithRange(personExample,ranges,pageable);
return new ResponseEntity<Page<Person>>(page,HttpStatus.OK);
}
}
원본 주소:https://github.com/wiselyman/query_with_example_and_range이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.