복붙노트

[SPRING] Spring JPA 스펙을 이용한 다중 컬럼 검색

SPRING

Spring JPA 스펙을 이용한 다중 컬럼 검색

스프링 부트 백엔드에서 다중 필드 검색을 만들고 싶습니다. 사양 을 사용하여이를 수행하는 방법?

환경

Springboot
Hibernate
Gradle
Intellij

프런트 엔드의 UI는 Jquery Datatable입니다. 각 열은 단일 문자열 검색 용어가 적용되도록합니다. 둘 이상의 열에 걸친 검색어는 a와 a로 결합됩니다.

이미 프런트 엔드에서 오는 필터가 이미 Java 객체로 채워져 있습니다.

1 단계 JPA 스펙 실행 프로그램 확장

public interface SomeRepository extends JpaRepository<Some, Long>, PagingAndSortingRepository<Some, Long>, JpaSpecificationExecutor {

2 단계 SomeSpec 새로운 클래스 만들기

이것은 코드가 어떻게 생겼는지와 어떻게 동작하는지에 관해서 분실 된 곳입니다.

각 열에 대해 메소드가 필요합니까? 루트 란 무엇이며 Criteria Builder는 무엇입니까? 그 밖의 무엇이 필요합니까?

저는 JPA에서 다소 새로운 것입니다. 그래서 누구든지 나를 위해 코드를 작성하는 것이 필요하지는 않지만 자세한 설명이 좋을 것입니다.

최신 정보 QueryDSL이 더 쉽게 접근 할 수있는 것으로 보입니다. 나는 Gradle을 사용하고있다. build.gradle을 이것에서 변경해야합니까?

해결법

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

    1.코드 데이터를 많이 쓰지 않아도 스프링 데이터가 QueryDSL을 지원한다고 생각할 수 있습니다. 즉, 실제로 코드를 작성하지 않아도됩니다.

    코드 데이터를 많이 쓰지 않아도 스프링 데이터가 QueryDSL을 지원한다고 생각할 수 있습니다. 즉, 실제로 코드를 작성하지 않아도됩니다.

    개요는 여기를 참조하십시오.

    https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

    기본적으로 저장소는 다음과 같습니다.

    public interface SomeRepository extends JpaRepository<Some, Long>,
         PagingAndSortingRepository<Some, Long>, QueryDslPredicateExecutor<Some>{
    
    }
    

    컨트롤러의 조건 자에 자동으로 바인드 된 요청 매개 변수를 가져올 수도 있습니다.

    여길 봐:

    https://spring.io/blog/2015/09/04/what-s-new-in-spring-data-release-gosling#querydsl-web-support

    컨트롤러가 다음과 같이 보일 것입니다.

      @Controller
      class SomeController {
    
        private final SomeRepository repository;
    
        @RequestMapping(value = "/", method = RequestMethod.GET)
        String index(Model model,
                     @QuerydslPredicate(root = Some.class) Predicate predicate,
                     Pageable pageable) {
    
          model.addAttribute("data", repository.findAll(predicate, pageable));
          return "index";
        }
      }
    

    위의 내용을 살펴보면 프로젝트에서 QueryDSL을 활성화하는 경우 일 뿐이며 UI는 다양한 조건 조합을 통해 데이터를 필터링, 정렬 및 페이지 할 수 있어야합니다.

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

    2.QueryDSL을 사용하지 않으려는 경우에는 사용자 고유의 스펙을 작성해야합니다. 우선, JpaSpecificationExecutor에서 저장소를 확장해야합니다. 제네릭을 추가해야합니다 (JpaSpecificationExecutor ).

    QueryDSL을 사용하지 않으려는 경우에는 사용자 고유의 스펙을 작성해야합니다. 우선, JpaSpecificationExecutor에서 저장소를 확장해야합니다. 제네릭을 추가해야합니다 (JpaSpecificationExecutor ).

    그 다음에는 세 개의 스팩 (각 컬럼 당 하나씩)을 만들어야 할 것이다. 스프링 문서에서 클래스의 정적 메소드로 이들 스팩을 정의한다. 기본적으로 사양을 만드는 것은 toPredicate (Root , CriteriaQuery , CriteriaBuilder)를 구현할 단 하나의 메서드 만있는 Specification 을 서브 클래스해야한다는 것을 의미합니다.

    Java 8을 사용하는 경우 lambda를 사용하여 익명 내부 클래스를 만들 수 있습니다 (예 :

     public class SomeSpecs {
         public static Specification<Some> withAddress(String address) {
              return (root, query, builder) -> {
                   // ...
              };
         }
     }
    

    실제 구현의 경우 루트를 사용하여 특정 노드 (예 : root.get ( "address"). 반면 CriteriaBuilder는 where 절을 정의하는 것입니다. builder.equal (..., ...).

    귀하의 경우에는 다음과 같은 것이 필요합니다.

     public class SomeSpecs {
         public static Specification<Some> withAddress(String address) {
              return (root, query, builder) -> builder.equal(root.get("address"), address);
         }
     }
    

    또는 LIKE 쿼리를 사용하려는 경우 다음을 사용할 수 있습니다.

    public class SomeSpecs {
         public static Specification<Some> withAddress(String address) {
              return (root, query, builder) -> builder.like(root.get("address"), "%" + address + "%");
         }
     }
    

    이제 필터링 할 다른 필드에 대해이 작업을 반복해야합니다. 그 후에는 모든 사양을 함께 사용해야합니다 (and (), or (), ...). 그런 다음 repository.findAll (Specification) 메서드를 사용하여 해당 사양을 기반으로 쿼리 할 수 ​​있습니다. 예를 들면 다음과 같습니다.

    public List<Some> getSome(String address, String name, Date date) {
        return repository.findAll(where(withAddress(address))
             .and(withName(name))
             .and(withDate(date));
    }
    

    정적 가져 오기를 사용하여 Name () 및 withDate ()를 사용하여 Address ()를 가져와 쉽게 읽을 수 있습니다. where () 메서드는 정적으로 가져올 수도 있습니다 (Specification.where ()에서 가져옴).

    주소 필드가 null 인 경우 필터링하지 않으므로 위의 메서드를 조정해야 할 수도 있음을 알고 있어야합니다. 다음과 같이 null을 반환하여이 작업을 수행 할 수 있습니다.

    public List<Some> getSome(String address, String name, Date date) {
        return repository.findAll(where(address == null ? null : withAddress(address))
             .and(name == null ? null : withName(name))
             .and(date == null ? null : withDate(date));
    }
    
  3. from https://stackoverflow.com/questions/46970689/multi-column-search-with-spring-jpa-specifications by cc-by-sa and MIT license