REST dotazovací jazyk so špecifikáciami JPA Spring Data

Tento článok je súčasťou série: • Dotazovací jazyk REST s kritériami Spring a JPA

• REST dotazovací jazyk so špecifikáciami JPA jarných dát (aktuálny článok) • REST dotazovací jazyk s jarnými údajmi JPA a Querydsl

• REST Query Language - Pokročilé vyhľadávacie operácie

• REST Query Language - implementácia ALEBO prevádzka

• REST dotazovací jazyk s RSQL

• REST Query Language s webovou podporou Querydsl

1. Prehľad

V tomto návode - postavíme a Hľadať / filtrovať REST API pomocou Spring Data JPA a špecifikácií.

V prvom článku tejto série sme sa začali zaoberať dotazovacím jazykom - riešením založeným na kritériách JPA.

Takže - prečo dotazovací jazyk? Pretože - pre akékoľvek dostatočne zložité API - vyhľadávanie / filtrovanie vašich zdrojov podľa veľmi jednoduchých polí jednoducho nestačí. Dotazovací jazyk je flexibilnejší a umožňuje vám filtrovať presne také zdroje, aké potrebujete.

2. Používateľ Subjekt

Najprv - začnime jednoduchým Používateľ entita pre naše vyhľadávacie API:

@Entity verejná trieda Používateľ {@Id @GeneratedValue (strategy = GenerationType.AUTO) private Long id; private String meno; private String priezvisko; súkromný reťazcový e-mail; súkromný int vek; // štandardné getre a setre}

3. Filtrovať pomocou Špecifikácia

Teraz - poďme priamo k najzaujímavejšej časti problému - dotazovaniu pomocou vlastného Spring Data JPA technické údaje.

Vytvoríme Špecifikácia používateľa ktorou sa vykonáva Špecifikácia rozhranie a ideme na odovzdať naše vlastné obmedzenie na zostavenie skutočného dotazu:

verejná trieda UserSpecification implementuje Specification {private SearchCriteria criteria; @Override public Predicate toPredicate (koreňový koreň, dotaz CriteriaQuery, tvorca CriteriaBuilder) {if (criteria.getOperation (). EqualsIgnoreCase (">")) {return builder.greaterThanOrEqualTo (root. Get (kritéria.getKey ()), kritériá. getValue (). toString ()); } else if (criteria.getOperation (). equalsIgnoreCase ("<")) {return builder.lessThanOrEqualTo (root. get (criteria.getKey ()), criteria.getValue (). toString ()); } else if (criteria.getOperation (). equalsIgnoreCase (":")) {if (root.get (criteria.getKey ()). getJavaType () == String.class) {return builder.like (root.get ( kritéria.getKey ()), "%" + kritériá.getValue () + "%"); } else {return builder.equal (root.get (criteria.getKey ()), criteria.getValue ()); }} return null; }}

Ako vidíme - tvoríme a Špecifikácia na základe niekoľkých jednoduchých obmedzení ktoré zastupujeme v nasledujúcich “Kritériá vyhľadávania" trieda:

public class SearchCriteria {private String key; súkromná prevádzka reťazca; hodnota súkromného objektu; }

The Kritériá vyhľadávania implementácia obsahuje základné znázornenie obmedzenia - a na základe tohto obmedzenia budeme vytvárať dotaz:

  • kľúč: názov poľa - napríklad krstné meno, Vek, … atď.
  • prevádzka: operácia - napríklad rovnosť, menej ako, ... atď.
  • hodnotu: hodnota poľa - napríklad john, 25,… atď.

Implementácia je samozrejme zjednodušená a dá sa vylepšiť; je to však pevný základ pre výkonné a flexibilné operácie, ktoré potrebujeme.

4. The UserRepository

Ďalej - poďme sa pozrieť na UserRepository; jednoducho rozširujeme JpaSpecificationExecutor získať nové špecifikácie API:

verejné rozhranie UserRepository rozširuje JpaRepository, JpaSpecificationExecutor {}

5. Vyskúšajte vyhľadávacie dotazy

Teraz - otestujme nové vyhľadávacie API.

Najprv vytvoríme niekoľko používateľov, aby sme ich mali pripravených pri spustení testov:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceJPAConfig.class}) @Transactional @TransactionConfiguration verejná trieda JPASpecificationsTest {@Autowired private UserRepository repository; súkromný používateľ userJohn; súkromný používateľ userTom; @ Pred public void init () {userJohn = nový používateľ (); userJohn.setFirstName ("John"); userJohn.setLastName ("Laň"); userJohn.setEmail ("[chránený e-mailom]"); userJohn.setAge (22); repository.save (userJohn); userTom = nový užívateľ (); userTom.setFirstName ("Tom"); userTom.setLastName ("Srnka"); userTom.setEmail ("[chránený e-mailom]"); userTom.setAge (26); repository.save (userTom); }}

Ďalej sa pozrime, ako nájsť používateľov pomocou krstné meno:

@Test public void givenLast_whenGettingListOfUsers_thenCorrect () {UserSpecification spec = new UserSpecification (new SearchCriteria ("lastName", ":", "doe")); Zoznam výsledkov = repository.findAll (spec); assertThat (userJohn, isIn (výsledky)); assertThat (userTom, isIn (výsledky)); }

Teraz sa pozrime, ako nájsť používateľa s daným meno aj priezvisko:

@ Test public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect () {UserSpecification spec1 = new UserSpecification (new SearchCriteria ("firstName", ":", "john")); UserSpecification spec2 = new UserSpecification (new SearchCriteria ("lastName", ":", "doe")); Zoznam výsledkov = repository.findAll (Specification.where (spec1). A (spec2)); assertThat (userJohn, isIn (výsledky)); assertThat (userTom, nie (isIn (výsledky))); }

Poznámka: Použili sme „kde“A„a”Až kombinovať špecifikácie.

Ďalej sa pozrime, ako nájsť používateľa s daným priezvisko aj minimálny vek:

@Test public void givenLastAndAge_whenGettingListOfUsers_thenCorrect () {UserSpecification spec1 = new UserSpecification (new SearchCriteria ("age", ">", "25")); UserSpecification spec2 = new UserSpecification (new SearchCriteria ("lastName", ":", "doe")); Zoznam výsledkov = repository.findAll (Specification.where (spec1). A (spec2)); assertThat (userTom, isIn (výsledky)); assertThat (userJohn, nie (isIn (results))); }

Teraz sa pozrime, ako hľadať Používateľ že vlastne neexistuje:

@Test public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect () {UserSpecification spec1 = new UserSpecification (new SearchCriteria ("firstName", ":", "Adam")); UserSpecification spec2 = new UserSpecification (new SearchCriteria ("lastName", ":", "Fox")); Zoznam výsledkov = repository.findAll (Specification.where (spec1). A (spec2)); assertThat (userJohn, nie (isIn (results))); assertThat (userTom, nie (isIn (výsledky))); }

Nakoniec - pozrime sa, ako nájsť a Používateľ krstné meno:

@Test public void givenPartialFirst_whenGettingListOfUsers_thenCorrect () {UserSpecification spec = new UserSpecification (new SearchCriteria ("firstName", ":", jo ")); Zoznam výsledkov = repository.findAll (spec); assertThat (userJohn, isIn (výsledky)); assertThat (userTom, nie (isIn (výsledky))); }

6. Kombinujte technické údaje

Ďalej - poďme sa pozrieť na kombináciu nášho zvyku technické údaje použiť viac obmedzení a filtrovať podľa viacerých kritérií.

Ideme implementovať staviteľ - UserSpecificationsBuilder - ľahko a plynulo kombinovať technické údaje:

public class UserSpecificationsBuilder {private final List params; public UserSpecificationsBuilder () {params = new ArrayList (); } public UserSpecificationsBuilder s (kľúč reťazca, operácia reťazca, hodnota objektu) {params.add (nové kritériá vyhľadávania (kľúč, operácia, hodnota)); vráťte to; } public Specification build () {if (params.size () == 0) {return null; } Zoznam špecifikácií = params.stream () .map (UserSpecification :: new) .collect (Collectors.toList ()); Výsledok špecifikácie = specs.get (0); pre (int i = 1; i <params.size (); i ++) {result = params.get (i) .isOrPredicate ()? Specification.where (result) .or (specs.get (i)): Specification.where (result) .and (specs.get (i)); } vrátiť výsledok; }}

7. UserController

Na záver - využime túto novú funkcionalitu hľadania / filtrovania perzistencie a nastaviť REST API - vytvorením a UserController s jednoduchým Vyhľadávanie prevádzka:

@Controller verejná trieda UserController {@Autowired private UserRepository repo; @RequestMapping (method = RequestMethod.GET, value = "/ users") @ResponseBody verejné vyhľadávanie v zozname (@RequestParam (value = "search") hľadanie reťazcov) {UserSpecificationsBuilder builder = nový UserSpecificationsBuilder (); Pattern pattern = Pattern.compile ("(\ w +?) (: |) (\ w +?),"); Matcher matcher = pattern.matcher (hľadať + ","); while (matcher.find ()) {builder.with (matcher.group (1), matcher.group (2), matcher.group (3)); } Špecifikácia spec = builder.build (); vrátiť repo.findAll (spec); }}

Upozorňujeme, že na podporu iných neanglických systémov slúži Vzor objekt je možné zmeniť ako:

Pattern pattern = Pattern.compile ("(\ w +?) (: |) (\ w +?),", Pattern.UNICODE_CHARACTER_CLASS);

Tu je príklad testovacej adresy URL na otestovanie rozhrania API:

// localhost: 8080 / users? search = lastName: doe, age> 25

A odpoveď:

[{"id": 2, "firstName": "tom", "lastName": "doe", "email": "[e-mail chránený]", "vek": 26}]

Pretože sú vyhľadávania v našom vyhľadávaní rozdelené „,“ Vzor napríklad hľadané výrazy nemôžu obsahovať tento znak. Vzor sa tiež nezhoduje s medzerami.

Ak chceme vyhľadať hodnoty obsahujúce čiarky, môžeme zvážiť použitie iného oddeľovača, napríklad „;“.

Ďalšou možnosťou by bola zmena vzoru na hľadanie hodnôt medzi úvodzovkami a potom ich odstránenie z hľadaného výrazu:

Pattern pattern = Pattern.compile ("(\ w +?) (: |) (\" ([^ \ "] +) \") ");

8. Záver

Tento výukový program sa venoval jednoduchej implementácii, ktorá môže byť základom výkonného dotazovacieho jazyka REST. Správne sme využili špecifikácie jarných údajov, aby sme zaistili, že rozhranie API nebude v dosahu domény a mať možnosť zvládnuť mnoho ďalších typov operácií.

The úplná implementácia tohto článku nájdete v projekte GitHub - jedná sa o projekt založený na Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.

Ďalšie » REST dotazovací jazyk s jarnými údajmi JPA a Querydsl « Predchádzajúci dotazovací jazyk REST s jarnými a JPA kritériami

$config[zx-auto] not found$config[zx-overlay] not found