1. введение
В этом уроке мы собираемся узнать, как запрашивать данные с помощью Spring Data | Query by Example API .
Во-первых, мы определим схему данных, которые мы хотим запросить. Далее мы рассмотрим несколько соответствующих классов из данных Spring. А затем мы рассмотрим несколько примеров.
Давайте начнем!
2. Данные Испытаний
Наши тестовые данные-это список имен пассажиров, а также место, которое они занимали.
Кузнец | Джилл | 50 |
Джексон | Канун | 94 |
Блоги | Фред | 22 |
Бобби | Рики | 36 |
Колиси | Сия | 85 |
3. Домен
Давайте создадим хранилище данных Spring, в котором мы нуждаемся, и предоставим наш класс домена и тип идентификатора.
Для начала мы смоделировали наш 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 . Как мы видим, он расширяет интерфейс QueryByExample Executor для поддержки запроса на примере:
public interface JpaRepositoryextends PagingAndSortingRepository , QueryByExampleExecutor {}
Этот интерфейс представляет больше вариантов метода find () , с которыми мы знакомы по данным Spring. Однако каждый метод также принимает экземпляр Example :
public interface QueryByExampleExecutor{ OptionalfindOne(Examplevar1);IterablefindAll(Examplevar1);IterablefindAll(Examplevar1, Sort var2);PagefindAll(Examplevar1, Pageable var2);long count(Examplevar1);boolean exists(Examplevar1); }
Во-вторых, интерфейс Example предоставляет методы для доступа к зонду , и Пример соответствует .
Важно понимать, что зонд является экземпляром нашей Сущности :
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()); } }
Таким образом, наш зонд и ваш Пример совпадений вместе определяют наш запрос.
5. Ограничения
Как и все остальное, запрос по примеру API имеет некоторые ограничения. Например:
- Операторы вложенности и группировки не поддерживаются, например: ( Имя = ?0 и фамилия = ?1) или Номер места = ?2
- Сопоставление строк включает только точное, без учета регистра, начало, конец, содержит и регулярное выражение
- Все типы, кроме String , являются точными-совпадают только
Теперь, когда мы немного лучше знакомы с API и его ограничениями, давайте рассмотрим несколько примеров.
6. Примеры
6.1. Сопоставление С Учетом Регистра
Давайте начнем с простого примера и поговорим о поведении по умолчанию:
@Test public void givenPassengers_whenFindByExample_thenExpectedReturned() { Exampleexample = 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() строит Example , используя Example Matcher.matching() .
Другими словами, точное совпадение будет выполнено для всех ненулевых свойств | Пассажира . Таким образом, сопоставление чувствительно к регистру в свойствах String .
Однако было бы не слишком полезно, если бы все, что мы могли сделать,-это точное совпадение всех ненулевых свойств.
Именно здесь появляется Пример соответствия . Создав свой собственный Пример соответствия , мы можем настроить поведение в соответствии с вашими потребностями.
6.2. Сопоставление Без Учета Регистра
Имея это в виду, давайте рассмотрим другой пример, на этот раз используя с Ignore Case() для достижения соответствия без учета регистра:
@Test public void givenPassengers_whenFindByExampleCaseInsensitiveMatcher_thenExpectedReturned() { ExampleMatcher caseInsensitiveExampleMatcher = ExampleMatcher.matchingAll().withIgnoreCase(); Exampleexample = 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. Пользовательское соответствие
Мы также можем настроить поведение наших совпадений на основе каждого свойства и сопоставить любое свойство с помощью Example Matcher.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()); Exampleexample = 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. Игнорирование свойств
С другой стороны, мы также можем захотеть запросить только подмножество наших свойств .
Мы достигаем этого, игнорируя некоторые свойства с помощью Example Matcher.ignore Paths(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"); Exampleexample = 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. Заключение
В этой статье мы продемонстрировали, как использовать запрос на примере API.
Мы продемонстрировали, как использовать Example и Example Matches вместе с интерфейсом QueryByExampleExecutor для запроса таблицы с использованием экземпляра данных примера.
В заключение, вы можете найти код на GitHub .