Spring Data JPA заявка за пример

1. Въведение

В този урок ще научим как да заявяваме данни с Spring Data Query чрез пример API .

Първо ще дефинираме схемата на данните, които искаме да направим. След това ще разгледаме няколко от съответните класове от Spring Data. И тогава ще разгледаме няколко примера.

Да започваме!

2. Тестовите данни

Нашите тестови данни са списък с имената на пътниците, както и мястото, което са заели.

Първо име Фамилия Номер на седалката
Джил Смит 50
Ева Джаксън 94
Фред Bloggs 22.
Рики Боби 36
Сия Колиси 85

3. Домейн

Нека създадем хранилището Spring Data, от което се нуждаем, и да предоставим нашия клас на домейн и тип id.

Като начало моделирахме нашия пътник като 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 {}

Този интерфейс представя повече варианти на метода find () , с които сме запознати от Spring Data. Всеки метод обаче приема и екземпляр от Пример :

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); }

На второ място, примерният интерфейс излага методи за достъп до сондата и ExampleMatcher .

Важно е да осъзнаете, че сондата е екземпляр на нашата Същност :

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
  • Съвпадението на низове включва само точно, без регистър, начало, край, съдържание и регулярно изражение
  • Всички видове, различни от String, са само с точно съвпадение

Сега, когато сме малко по-запознати с 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 () .

С други думи, ще бъде извършено точно съвпадение на всички ненулеви свойства на Пътника . По този начин, съвпадението е чувствително към регистъра на свойствата String .

Въпреки това, не би било твърде полезно, ако всичко, което можехме да направим, беше точно съвпадение на всички ненулеви свойства.

Това е мястото, където се появява 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.

Демонстрирахме как да използваме Example и ExampleMatcher заедно с интерфейса QueryByExampleExecutor за заявка на таблица, използвайки примерен екземпляр от данни.

В заключение можете да намерите кода на GitHub.