복붙노트

[SPRING] 엔터티를 필터링하기 위해 Querydsl 및 Spring Data로 'REST API 쿼리 언어'를 쉽게 구현하는 방법은 무엇입니까?

SPRING

엔터티를 필터링하기 위해 Querydsl 및 Spring Data로 'REST API 쿼리 언어'를 쉽게 구현하는 방법은 무엇입니까?

엔터티를 필터링하기 위해 스프링 데이터로 일종의 'REST API 쿼리 언어'를 쉽게 구현하는 방법은 무엇입니까?

예를 들어, 다음 Person 엔티티의 경우 :

@Data
@Entity
public class Person {

  @Id
  @GeneratedValue
  private Long id;

  private LocalDate dob; // date of birth

  private String name;

  @Formula("timestampdiff('year', dob, now())")
  private Integer age;

  public Person(String name, LocalDate dob) {
    this.name = name;
    this.dob = dob;
  }
}

그러한 요청으로 데이터를 얻고 싶습니다.

GET /people?name=jo&age=18&page=1&sort=name,desc

즉, 'jo'(대소 문자 구별 없음) 및 18 세의 이름을 가진 모든 사람들의 첫 페이지를 가져 와서 내림차순으로 이름순으로 정렬합니다. '

해결법

  1. ==============================

    1.Querydsl 웹 지원, 웹 지원 부분 인 스프링 데이터 확장을 사용하여 우리의 엔티티를 필터링하는 일종의 'REST API 쿼리 언어'를 쉽게 구현할 수 있습니다.

    Querydsl 웹 지원, 웹 지원 부분 인 스프링 데이터 확장을 사용하여 우리의 엔티티를 필터링하는 일종의 'REST API 쿼리 언어'를 쉽게 구현할 수 있습니다.

    우리가 필요로하는 것은 다음과 같습니다.

    1) 우리의 저장소를 QuerydslPredicateExecutor에서 확장하고,

    2) @QuerydslPredicate 어노테이션을 가진 Predicate를 인수로 REST 컨트롤러 메소드에 추가한다.

    3) 저장소의 findAll 메소드에서이 술어를 사용하십시오.

    public interface PersonRepo extends JpaRepository<Person, Long>, QuerydslPredicateExecutor<Person> {
    } 
    
    @RequiredArgsConstructor
    @RestController
    @RequestMapping("/people")
    public class PersonController {
    
        private final PersonRepo personRepo;
    
        @GetMapping
        public ResponseEntity getFiltered(@QuerydslPredicate(root = Person.class) Predicate predicate, Pageable pageable) {
            return ResponseEntity.ok(personRepo.findAll(predicate, pageable)));
        }
    }
    

    그러면 데이터를 요청할 수 있습니다.

    GET /people?name=John&age=18&page=1&sort=name,desc
    

    다음으로 필터와 같이 대소 문자를 구분하지 않아야합니다. 이를 위해 QuerydslBinderCustomizer에서 Repo를 확장하고 사용자 정의 메소드를 재정의합니다 (repo에서 바로).

    public interface PersonRepo extends
            JpaRepository<Person, Long>,
            QuerydslPredicateExecutor<Person>,
            QuerydslBinderCustomizer<QPerson> {
    
        @Override
        default void customize(QuerydslBindings bindings, QPerson person) {
    
            // Make case-insensitive 'like' filter for all string properties 
            bindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
        }
    }
    

    작동 시키려면 컨트롤러 메서드의 @QuerydslPredicate에 매개 변수 바인딩을 추가해야합니다.

    @GetMapping
    public ResponseEntity getFiltered(
        @QuerydslPredicate(root = Person.class, bindings = PersonRepo.class) Predicate predicate, 
        Pageable pageable
    ) {
        return ResponseEntity.ok(personRepo.findAll(predicate, pageable)));
    }
    

    이제 우리는 질문에서 묻는 것처럼 우리의 데이터를 요청할 수 있습니다 :

    GET /people?name=jo&age=18&page=1&sort=name,desc
    

    QuerydslBinderCustomizer를 사용하면 더 복잡한 필터를 구현할 수 있습니다 (예 : 필터를 더 크게 또는 같게 만들기).이 코드를 추가하여 메소드를 사용자 정의하십시오.

    bindings.bind(person.age).all((path, value) -> {
        Iterator<? extends Integer> it = value.iterator();
        Integer from = it.next();
        if (value.size() >= 2) {
            Integer to = it.next();
            return Optional.of(path.between(from, to)); // between
        } else {
            return Optional.of(path.goe(from)); // greater or equal
        }
    });
    

    요청에 두 개의 연령 매개 변수를 지정하면이 매개 변수 사이에 연령이 기록 된 모든 레코드가 생성됩니다. 연령 매개 변수를 하나만 지정하면 나이가 더 크거나 같은 값으로 기록됩니다.

    GET /people?age=18&age=30
    

    18 세에서 30 세 사이의 모든 사람들을 구하십시오.

    GET /people?age=18
    

    ... 나이가 18 이상인 모든 사람들을 얻으십시오.

    마지막으로 엔티티 ID와 같이 필터에서 불필요한 일부 속성을 제외 할 수 있습니다 (메서드를 사용자 정의하려면이 코드를 추가하십시오).

    bindings.excluding(person.id);
    

    Querydsl Web Support를 사용하려면 Spring Boot 프로젝트에 다음과 같은 의존성과 플러그인을 추가해야합니다.

    <dependencies>
        <!-- ... -->
    
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-jpa</artifactId>
        </dependency>
    
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-apt</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <!-- ... -->
    
            <plugin>
                <groupId>com.mysema.maven</groupId>
                <artifactId>apt-maven-plugin</artifactId>
                <version>1.1.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/generated-sources/annotations</outputDirectory>
                            <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    

    그렇다면 우리 프로젝트의 'Q-classes'를 구축하기 위해 프로젝트를 컴파일해야합니다.

    내 repo에서 찾을 수있는 전체 예제 데모 : sb-querydsl-sd-demo 및이 데모의 Postman API-docs : 여기에서는 Querydsl 및 Spring Data를 사용한 REST 쿼리 언어입니다.

  2. from https://stackoverflow.com/questions/51127468/how-to-easy-implement-rest-api-query-language-with-querydsl-and-spring-data-to by cc-by-sa and MIT license