예제 별 SpringData JPA 쿼리

1. 소개

이 튜토리얼에서는 Spring Data Query by Example API를 사용하여 데이터를 쿼리하는 방법을 배웁니다 .

먼저 쿼리 할 데이터의 스키마를 정의합니다. 다음으로 SpringData의 관련 클래스 몇 가지를 살펴 보겠습니다. 그런 다음 몇 가지 예를 살펴 보겠습니다.

시작하자!

2. 테스트 데이터

테스트 데이터는 승객 이름과 그들이 차지한 좌석 목록입니다.

이름 좌석 번호
처녀 스미스 50
이브 잭슨 94
프레드 블로그 22
리키 바비 36
시야 Kolisi 85

3. 도메인

우리가 필요로하는 Spring Data Repository를 생성하고 도메인 클래스와 id 유형을 제공합시다.

먼저 Passenger 를 JPA 엔티티로 모델링했습니다 .

@Entity class Passenger { @Id @GeneratedValue @Column(nullable = false) private Long id; @Basic(optional = false) @Column(nullable = false) private String firstName; @Basic(optional = false) @Column(nullable = false) private String lastName; @Basic(optional = false) @Column(nullable = false) private int seatNumber; // constructor, getters etc. }

JPA를 사용하는 대신 다른 추상화로 모델링 할 수 있습니다.

4. 예제 API로 쿼리

먼저 JpaRepository 인터페이스를 살펴 보겠습니다 . 보시다시피 QueryByExampleExecutor 인터페이스를 확장하여 예제 별 쿼리를 지원합니다.

public interface JpaRepository extends PagingAndSortingRepository, QueryByExampleExecutor {}

이 인터페이스는 SpringData에서 익숙한 find () 메서드 의 더 많은 변형을 소개 합니다. 그러나 각 메서드는 Example 의 인스턴스도 허용합니다 .

public interface QueryByExampleExecutor {  Optional findOne(Example var1);  Iterable findAll(Example var1);  Iterable findAll(Example var1, Sort var2);  Page findAll(Example var1, Pageable var2);  long count(Example var1);  boolean exists(Example var1); }

둘째, Example 인터페이스는 프로브ExampleMatcher 에 액세스하는 메서드를 노출합니다 .

프로브Entity 의 인스턴스 임을 인식하는 것이 중요합니다 .

public interface Example { static  org.springframework.data.domain.Example of(T probe) { return new TypedExample(probe, ExampleMatcher.matching()); } static  org.springframework.data.domain.Example of(T probe, ExampleMatcher matcher) { return new TypedExample(probe, matcher); } T getProbe(); ExampleMatcher getMatcher(); default Class getProbeType() { return ProxyUtils.getUserClass(this.getProbe().getClass()); } }

요약하면 프로브ExampleMatcher가 함께 쿼리를 지정합니다.

5. 제한

모든 것과 마찬가지로 Query by Example API에는 몇 가지 제한 사항이 있습니다. 예를 들면 :

  • 중첩 및 그룹화 문은 지원되지 않습니다. 예 : ( firstName =? 0 및 lastName =? 1) 또는 seatNumber =? 2
  • 문자열 일치에는 정확한 대소 문자 구분, 시작, 종료, 포함 및 정규식 만 포함됩니다.
  • 문자열 이외의 모든 유형 은 정확히 일치 만 가능합니다.

이제 API와 그 제한 사항에 대해 조금 더 익숙해 졌으므로 몇 가지 예를 살펴 보겠습니다.

6. 예

6.1. 대소 문자 구분 일치

간단한 예제로 시작하여 기본 동작에 대해 이야기하겠습니다.

@Test public void givenPassengers_whenFindByExample_thenExpectedReturned() { Example example = Example.of(Passenger.from("Fred", "Bloggs", null)); Optional actual = repository.findOne(example); assertTrue(actual.isPresent()); assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get()); }

특히 정적 Example.of () 메서드는 ExampleMatcher.matching ()을 사용하여 Example 을 빌드합니다 .

즉, 정확히 일치하는 모든 null이 아닌 속성에 수행됩니다여객 . 따라서 일치는 String 속성 에서 대소 문자를 구분 합니다.

그러나 우리가 할 수있는 모든 것이 null이 아닌 모든 속성에 대해 정확히 일치하는 것이라면 그다지 유용하지 않을 것입니다.

이것이 ExampleMatcher 가 들어오는 곳 입니다. 우리 자신의 ExampleMatcher 를 구축함으로써 우리는 우리의 필요에 맞게 동작을 사용자 정의 할 수 있습니다.

6.2. 대소 문자를 구분하지 않는 일치

이를 염두에두고 이번에는 withIgnoreCase () 를 사용하여 대소 문자를 구분하지 않는 일치를 달성 하는 또 다른 예를 살펴 보겠습니다 .

@Test public void givenPassengers_whenFindByExampleCaseInsensitiveMatcher_thenExpectedReturned() { ExampleMatcher caseInsensitiveExampleMatcher = ExampleMatcher.matchingAll().withIgnoreCase(); Example example = Example.of(Passenger.from("fred", "bloggs", null), caseInsensitiveExampleMatcher); Optional actual = repository.findOne(example); assertTrue(actual.isPresent()); assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get()); }

이 예제에서는 먼저 ExampleMatcher.matchingAll ()을 호출 했습니다 . 이전 예제에서 사용한 ExampleMatcher.matching () 과 동일한 동작을 합니다.

6.3. 맞춤 매칭

속성별로 매처의 동작을 조정하고 ExampleMatcher.matchingAny ()를 사용하여 모든 속성을 일치 시킬 수도 있습니다 .

@Test public void givenPassengers_whenFindByExampleCustomMatcher_thenExpectedReturned() { Passenger jill = Passenger.from("Jill", "Smith", 50); Passenger eve = Passenger.from("Eve", "Jackson", 95); Passenger fred = Passenger.from("Fred", "Bloggs", 22); Passenger siya = Passenger.from("Siya", "Kolisi", 85); Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); ExampleMatcher customExampleMatcher = ExampleMatcher.matchingAny() .withMatcher("firstName", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()) .withMatcher("lastName", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()); Example example = Example.of(Passenger.from("e", "s", null), customExampleMatcher); List passengers = repository.findAll(example); assertThat(passengers, contains(jill, eve, fred, siya)); assertThat(passengers, not(contains(ricki))); }

6.4. 속성 무시

반면에 속성의 하위 집합에 대해서만 쿼리 할 수도 있습니다 .

ExampleMatcher.ignorePaths (String… paths)를 사용하여 일부 속성을 무시하면됩니다 .

@Test public void givenPassengers_whenFindByIgnoringMatcher_thenExpectedReturned() { Passenger jill = Passenger.from("Jill", "Smith", 50); Passenger eve = Passenger.from("Eve", "Jackson", 95); Passenger fred = Passenger.from("Fred", "Bloggs", 22); Passenger siya = Passenger.from("Siya", "Kolisi", 85); Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); ExampleMatcher ignoringExampleMatcher = ExampleMatcher.matchingAny() .withMatcher("lastName", ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()) .withIgnorePaths("firstName", "seatNumber"); Example example = Example.of(Passenger.from(null, "b", null), ignoringExampleMatcher); List passengers = repository.findAll(example); assertThat(passengers, contains(fred, ricki)); assertThat(passengers, not(contains(jill)); assertThat(passengers, not(contains(eve)); assertThat(passengers, not(contains(siya)); }

7. 결론

이 기사에서는 Query by Example API를 사용하는 방법을 설명했습니다.

예제 데이터 인스턴스를 사용하여 테이블을 쿼리하기 위해 QueryByExampleExecutor 인터페이스 와 함께 ExampleExampleMatcher 를 사용하는 방법을 시연했습니다 .

결론적으로 GitHub에서 코드를 찾을 수 있습니다.