복붙노트

[SPRING] Spring 데이터 REST의 QueryDSL 통합을 사용하여 더 복잡한 쿼리를 수행 할 수 있습니까?

SPRING

Spring 데이터 REST의 QueryDSL 통합을 사용하여 더 복잡한 쿼리를 수행 할 수 있습니까?

현재 클라이언트가 특정 엔터티의 대부분의 속성을 쉽게 필터링 할 수 있도록 REST API를 구축 중입니다. QueryDataL과 Spring 데이터 REST (Oliver Gierke의 사례)를 함께 사용하면 클라이언트가 속성 (예 : / users? firstName = Dennis & lastName = Laumen)을 참조하는 쿼리 매개 변수를 조합하여 필터링 할 수 있으므로 원하는 내용을 90 %까지 쉽게 얻을 수 있습니다. ).

QuerydslBinderCustomizer 인터페이스 (예 : 대소 문자를 구분하지 않는 검색 또는 부분 문자열 일치의 경우)를 구현하여 쿼리 매개 변수와 엔티티 속성 간의 매핑을 사용자 정의 할 수도 있습니다. 이것은 모두 훌륭하지만 클라이언트가 범위를 사용하여 일부 유형을 필터링 할 수 있기를 원합니다. 예를 들어, 생년월일과 같은 속성에 관해서는 / users? dateOfBirthFrom = 1981-1-1 & dateOfBirthTo = 1981-12-31과 같은 것을하고 싶습니다. 숫자 기반 속성 인 / users? idFrom = 100 & idTo = 200에서도 마찬가지입니다. QuerydslBinderCustomizer 인터페이스를 사용하여 이것이 가능해야한다는 생각이 들지만이 두 라이브러리 간의 통합은 매우 광범위하게 문서화되어 있지 않습니다.

결론은 Spring Data REST와 QueryDSL을 사용하여 가능합니까? 그렇다면 어떻게?

해결법

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

    1.난 당신이 다음과 같은 사용자 정의를 사용하여 작동하도록 할 수 있어야한다고 생각 :

    난 당신이 다음과 같은 사용자 정의를 사용하여 작동하도록 할 수 있어야한다고 생각 :

    bindings.bind(user.dateOfBirth).all((path, value) -> {
    
      Iterator<? extends LocalDate> it = value.iterator();
      return path.between(it.next(), it.next());
    });
    

    여기서 중요한 것은? 생년월일 = ... & 생년월일 = (속성을 두 번 사용)과 .all (...) 바인딩을 사용하면 제공된 모든 값에 액세스 할 수 있습니다.

    Spring이 들어오는 String을 LocalDate 인스턴스로 올바르게 변환 할 수 있도록 User의 dateOfBirth 속성에 @DateTimeFormat 주석을 추가해야합니다.

    람다는 현재 Collection 를 확장하면 개별 요소의 꼬리뼈가 엉망이되게 할 수 있습니다. 그러나 향후 릴리스에서는이를 변경하여 목록을 노출 할 수 있다고 생각합니다.

  2. ==============================

    2.일부 의견에 게시되었으므로 필자는 creationDateFrom 및 creationDateTo라는 필드 이름에 따라 다른 동작이 필요할 수도있었습니다. 작동 시키려면 다음을 수행했습니다.

    일부 의견에 게시되었으므로 필자는 creationDateFrom 및 creationDateTo라는 필드 이름에 따라 다른 동작이 필요할 수도있었습니다. 작동 시키려면 다음을 수행했습니다.

    먼저 엔티티 클래스에 @QueryEntity 주석과 두 개의 필드를 추가했습니다. 필드에 주석을 달았습니다 :

    @QueryEntity
    @Entity
    public class MyEntity implements Serializable {
      ...
    
      @Column(updatable = false)
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private Date creationDate;
    
      @Transient
      @Getter(value = AccessLevel.PRIVATE)
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private Date creationDateTo;
    
      @Transient
      @Getter(value = AccessLevel.PRIVATE)
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private Date creationDateFrom;
    
      ...
    }  
    

    그런 다음 querydsl 클래스를 생성하는 방법을 JPAAnnotationProcessor에서 QuerydslAnnotationProcessor로 변경했습니다. 이 방법은 @Transient로 주석 된 필드는 여전히 QMyEntity에서 생성되지만 지속되지 않습니다. pom의 플러그인 구성 :

    <plugin>
        <groupId>com.mysema.maven</groupId>
        <artifactId>apt-maven-plugin</artifactId>
        <version>1.1.3</version>
        <executions>
            <execution>
                <phase>generate-sources</phase>
                <goals>
                    <goal>process</goal>
                </goals>
                <configuration>
                    <outputDirectory>target/generated-sources/annotations</outputDirectory>
                    <processor>com.querydsl.apt.QuerydslAnnotationProcessor</processor>
                </configuration>
            </execution>
        </executions>
    </plugin>
    

    마지막으로 QuerydslBinderCustomizer를 확장하고 creationDateFrom 및 creationDateTo와 관련된 바인딩을 사용자 정의했지만 creationDate에 적합한 로직을 적용했습니다.

    @Override
    default void customize(QuerydslBindings bindings, QMyEntity root) {
        bindings.bind(root.creationDateFrom).first((path, value) -> 
                                                    root.creationDate.after(value));
        bindings.bind(root.creationDateTo).first((path, value) ->
                                                   root.creationDate.before(value));
    }
    

    이 모든 기능을 사용하여 하나 또는 둘 다 기준을 사용하여 날짜 범위 쿼리를 수행 할 수 있습니다.

    http://localhost:8080/myentities?creation_date_to=2017-05-08
    http://localhost:8080/myentities?creation_date_from=2017-01-01
    http://localhost:8080/myentities?creation_date_from=2017-01-01&creation_date_to=2017-05-08
    
  3. ==============================

    3.이것은 모든 날짜 필드에 대한 제네릭 바인딩에 사용 된 것이며, 항상 2 개의 값을 기대합니다.

    이것은 모든 날짜 필드에 대한 제네릭 바인딩에 사용 된 것이며, 항상 2 개의 값을 기대합니다.

    bindings.bind(Date.class).all((final DateTimePath<Date> path, final Collection<? extends Date> values) -> {
        final List<? extends Date> dates = new ArrayList<>(values);
        Collections.sort(dates);
        if (dates.size() == 2) {
            return path.between(dates.get(0), dates.get(1));
        }
        throw new IllegalArgumentException("2 date params(from & to) expected for:" + path + " found:" + values);
    });
    

    이것은 날짜 시간 필드입니다. 날짜 필드의 경우, 단일 매개 변수를 가져올 때 path.eq ()가 맞는 것 같습니다.

  4. from https://stackoverflow.com/questions/35155824/can-spring-data-rests-querydsl-integration-be-used-to-perform-more-complex-quer by cc-by-sa and MIT license