2016-12-09 1 views
3

현재 저는 교육용으로 Spring Boot REST API 프로젝트를 사용하고 있습니다. MySQL 데이터베이스에로드 된 22 개의 열이있는 상당히 큰 테이블을 가지고 있으며 사용자에게 여러 열의 결과를 필터링 할 수있는 기능을 제공하려고합니다 (이 예제에서는 6 개라고 가정 해 보겠습니다).Java Spring REST API 많은 선택적 매개 변수 처리

현재 저장소를 확장 중이며 findByParam1 및 findByParam2 및 findByParam1OrderByParam2Desc 등의 메소드를 초기화했으며 의도 한대로 작동하는지 확인했습니다. 내 질문에 당신에게 접근하는 가장 좋은 방법은 조건부/저장소 방법 변형의 어리석은 금액을 작성하지 않고 사용자가 6 RequestParams 모든 활용할 수있는 능력을 허용 접근이다. 예를 들어, 나는 모든 결과를 얻기 위해 url home/get-data/을 방문 할 수있는 권한을 사용자에게 주려고합니다. home/get-data? param1 = xx는 param1 및 잠재적으로 home/get-data ? param1 = xx & param2 = yy ... & param6 = zz 모든 선택적 매개 변수를 필터링합니다.

다음은 내 컨트롤러의 관련 청크 모습입니다 (대략).

@RequestMapping(value = "/get-data", method = RequestMethod.GET) 
public List<SomeEntity> getData(@RequestParam Map<String, String> params) { 
    String p1 = params.get("param1"); 
    if(p1 != null) { 
     return this.someRepository.findByParam1(p1); 
    } 
    return this.someRepository.findAll(); 
} 

내 문제가 지금까지 내가 이것에 대해 진행하고있는 방법은 내가 기본적으로 N해야한다는 의미입니다! 필자가 필터링하고자하는 필드/열의 양과 같은 n을 사용하여이 기능을 지원하는 저장소의 메소드 양. 이 핸들링에 접근하는 더 좋은 방법이 있을지도 모르겠다. 아마도 장소에서 리포지토리를 필터링 할 때, 사용자가 실제로 어떤 필터를 채웠는지 확인하기 위해지도를 확인하면서 '적절한 위치에'필터를 걸 수 있을까?

편집 : 그래서 현재 아래 J. West의 의견과 관련있는 '해킹'솔루션을 구현 중입니다. 나는 사용자가 요청 URL에있는 모든 n 개의 매개 변수를 지정한다고 가정하고 그렇지 않은 경우 (예를 들어 p1-p4는 지정하지만 p5 및 p6은 지정하지 않음) SQL에 대해 '%'와 (과) 일치하는 SQL을 생성합니다. 포함되지 않은 매개 변수. 그것은 ... 같이 보일 것이다

@Query("select u from User u where u.p1 = :p1 and u.p2 = :p2 ... and u.p6 = :p6") 
List<User> findWithComplicatedQueryAndSuch; 

와 컨트롤러의

은 P5와 P6는지도에서 널 (null) 인 경우에, 나는 감지 할 그렇다면, 단순히 문자열 '%'로 변경합니다. 나는이 일을 더 정확하고 직관적 인 방법으로 생각하지만 아직 그 종류의 것을 찾을 수는 없습니다.

+0

흠,이 힘든 일이다. 저는 Spring이 이와 같은 것을 지원한다고 확신합니다. 정확히 무엇인지는 모르겠습니다. 나는 궁금해서 지금 문서를보고있다. 잠재적으로 '해킹 된'해결책으로 전체 객체를 반환 한 다음 포함시키지 않으려는 필드를 반복하고 'null'할 수 있습니다. 객체를 매핑하기 때문에 올바른 방법으로 작업하더라도, 당신이 쿼리에서 반환하지 않는 필드는 null이 될 것입니다. –

+0

나는 당신이 의미하는 바가 내가 포함하고 싶지 않은 필드를 100 % 확신하지 못합니다. 일명, 쓰지 않아도되는데 어떻게 도움이 될까요? 밖으로 N findByP1 및 findByP1andP2 및 findByP1andP3 같은 저장소 기능의 계승 양 등? 에이 난 그냥 사용자가 항상 6 개 매개 변수 및 필터링되어 가정 내가 지금 잘 구현하고있는 해키 방법 (대답을 업데이트)과 유사 할 수있다 그렇지 않다면 기본적으로 LIKE '%'와 같은 SQL을 생성하여 기본적으로 필터링하지 않습니다. 포함하지 않으려는 필드가 null로 무엇을 의미합니까? – purdoo

+0

당신이 묻는 것을 오해 한 것 같습니다. . 탁 이 커스텀'JpaSpecificationExecutor'를 만들 때이 링크를 보시면 올바른 경로에있는 것처럼 보입니다. http://www.cubrid.org/wiki_ngrinder/entry/how-to-create-dynamic-queries-in-springdata –

답변

4

당신은 JpaSpecificationExecutorSpecification 사용자 정의 쉽게이 작업을 수행 할 수 있습니다 https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

내가 그 DTO에 따라 사양을 구축, 모든 옵션 가져 오기 PARAMS를 포함하는 DTO와의 HashMap을 대체 할 것이다, 분명 당신은 또한 유지할 수 있습니다 HashMap을 기반으로 스펙을 빌드하십시오. 기본적으로

:

public class VehicleFilter implements Specification<Vehicle> 
{ 
    private String art; 
    private String userId; 
    private String vehicle; 
    private String identifier; 

    @Override 
    public Predicate toPredicate(Root<Vehicle> root, CriteriaQuery<?> query, CriteriaBuilder cb) 
    { 
     ArrayList<Predicate> predicates = new ArrayList<>(); 

     if (StringUtils.isNotBlank(art)) 
     { 
      predicates.add(cb.equal(root.get("art"), art)); 
     } 
     if (StringUtils.isNotBlank(userId)) 
     { 
      predicates.add(cb.equal(root.get("userId"), userId)); 
     } 
     if (StringUtils.isNotBlank(vehicle)) 
     { 
      predicates.add(cb.equal(root.get("vehicle"), vehicle)); 
     } 
     if (StringUtils.isNotBlank(identifier)) 
     { 
      predicates.add(cb.equal(root.get("identifier"), fab)); 
     } 

     return predicates.size() <= 0 ? null : cb.and(predicates.toArray(new Predicate[predicates.size()])); 
    } 

// getter & setter 
} 

그리고 컨트롤러 :

@RequestMapping(value = "/{ticket}/count", method = RequestMethod.GET) 
public long getItemsCount(
    @PathVariable String ticket, 
    VehicleFilter filter, 
    HttpServletRequest request 
) throws Exception 
{ 
    return vehicleService.getCount(filter); 
} 

서비스 :

@Override 
public long getCount(VehicleFilter filter) 
{ 
    return vehicleRepository.count(filter); 
} 

저장소 :

@Repository 
public interface VehicleRepository extends JpaRepository<Vehicle, Integer>, JpaSpecificationExecutor<Vehicle> 
{ 
} 

회사 코드를 적용한 간단한 예를 들어 보겠습니다.

+0

나는 바른 길을 가고 있었다. 매우 흥미 롭습니다. 저는 이런 식으로 유스 케이스를 사용 해본 적이 없지만,해야만한다면 어떻게해야하는지 이제 알았 기 때문에 기쁩니다. –

+0

컨트롤러에서 "향상된"DTO (실제로는 DTO가 아닌)를 바로 사용할 수 있으므로 기본적으로 오버 헤드가없는 대용량 쿼리 수정을 지원하는 매우 쉽고 깨끗한 솔루션입니다. – dav1d

1

적은 코딩 또 다른 해결책은 스프링 MVC와 QueryDsl 통합을 사용하는 것입니다. 모든 요청 매개 변수가 자동으로 도메인 속성 중 하나를 해결하고 쿼리에 추가됩니다이 방법을 사용하여

. 참조 검사의 경우

는 문서 https://spring.io/blog/2015/09/04/what-s-new-in-spring-data-release-gosling#querydsl-web-support 및 예제 프로젝트 https://github.com/spring-projects/spring-data-examples/tree/master/web/querydsl