REST dotazovací jazyk s jarnými údajmi JPA a Querydsl

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

• Dotazovací jazyk REST so špecifikáciami JPA Spring Data

• Dotazovací jazyk REST s jarnými údajmi JPA a Querydsl (aktuálny článok) • Dotazovací jazyk REST - 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 výučbe sa zameriavame na vytvorenie dotazovacieho jazyka pre a REST API pomocou Spring Data JPA a Querydsl.

V prvých dvoch článkoch tejto série sme vytvorili rovnakú funkcionalitu vyhľadávania / filtrovania pomocou JPA Criteria a Spring Data JPA Specifications.

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. Konfigurácia dotazu

Najprv - pozrime sa, ako nakonfigurovať náš projekt tak, aby používal Querydsl.

Musíme pridať nasledujúce závislosti pom.xml:

 com.querydsl querydsl-apt 4.2.2 com.querydsl querydsl-jpa 4.2.2 

Ďalej je potrebné nakonfigurovať doplnok APT - nástroj na spracovanie anotácií:

 com.mysema.maven apt-maven-plugin 1.1.3 cieľ procesu / generované-zdroje / java com.mysema.query.apt.jpa.JPAAnnotationProcessor 

Toto vygeneruje typy Q pre naše entity.

3. The MyUser Subjekt

Ďalej - poďme sa pozrieť na „MyUser„Entita, ktorú použijeme v našom rozhraní Search API:

@Entity public class MyUser {@Id @GeneratedValue (strategy = GenerationType.AUTO) private Long id; private String meno; private String priezvisko; súkromný reťazcový e-mail; súkromný int vek; }

4. Vlastné Predikát Ži PathBuilder

Teraz - vytvorme si zvyk Predikát na základe niektorých svojvoľných obmedzení.

Používame PathBuilder tu namiesto automaticky generovaných typov Q, pretože potrebujeme dynamicky vytvárať cesty pre abstraktnejšie použitie:

verejná trieda MyUserPredicate {súkromné ​​kritériá vyhľadávacieho kritéria; public BooleanExpression getPredicate () {PathBuilder entityPath = nový PathBuilder (MyUser.class, "užívateľ"); if (isNumeric (criteria.getValue (). toString ())) {NumberPath path = entityPath.getNumber (criteria.getKey (), Integer.class); int hodnota = Integer.parseInt (criteria.getValue (). toString ()); switch (criteria.getOperation ()) {case ":": návratová cesta.eq (hodnota); case ">": return path.goe (value); prípad "<": návratová cesta.loe (hodnota); }} else {cesta StringPath = entityPath.getString (kritéria.getKey ()); if (criteria.getOperation (). equalsIgnoreCase (":")) {return path.containsIgnoreCase (criteria.getValue (). toString ()); }} return null; }}

Všimnite si, ako je implementovaný predikát všeobecne sa zaoberá viacerými typmi operácií. Je to preto, že dotazovací jazyk je podľa definície otvorený jazyk, v ktorom môžete potenciálne filtrovať podľa ľubovoľného poľa pomocou akejkoľvek podporovanej operácie.

Na predstavenie tohto druhu kritérií otvoreného filtrovania používame jednoduchú, ale dosť flexibilnú implementáciu - Kritériá vyhľadávania:

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

The Kritériá vyhľadávania obsahuje podrobnosti, ktoré potrebujeme na predstavenie obmedzenia:

  • 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ď

5. MyUserRepository

Teraz - poďme sa pozrieť na našu MyUserRepository.

Potrebujeme svoje MyUserRepository predĺžiť QuerydslPredicateExecutor aby sme mohli použiť Predikáty neskôr na filtrovanie výsledkov vyhľadávania:

verejné rozhranie MyUserRepository rozširuje JpaRepository, QuerydslPredicateExecutor, QuerydslBinderCustomizer {@Override predvolené verejné void customize (väzby QuerydslBindings, koreň QMyUser) {bindings.bind (String.class) .first ((SingleValueBinding) StringExpression :: väzby.vynímajúce (root.email); }}

Všimnite si, že tu používame vygenerovaný typ Q pre MyUser subjekt, ktorý bude pomenovaný QMyUser.

6. Kombinujte Predikáty

Ďalej - poďme sa pozrieť na kombináciu predikátov na použitie viacerých obmedzení pri filtrovaní výsledkov.

V nasledujúcom príklade - pracujeme so staviteľom - MyUserPredicatesBuilder - kombinovať Predikáty:

public class MyUserPredicatesBuilder {private List params; public MyUserPredicatesBuilder () {params = new ArrayList (); } public MyUserPredicatesBuilder with (String key, String operation, Object value) {params.add (new SearchCriteria (key, operation, value)); vráťte to; } public BooleanExpression build () {if (params.size () == 0) {return null; } Zoznam predikátov = params.stream (). Mapa (param -> {MyUserPredicate predicate = nový MyUserPredicate (param); návrat predicate.getPredicate ();}). Filter (Objects :: nonNull) .collect (Collectors.toList () ); Výsledok BooleanExpression = Expressions.asBoolean (true) .isTrue (); pre (predikát BooleanExpression: predikáty) {výsledok = výsledok.a (predikát); } vrátiť výsledok; }}

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

Ďalej - otestujme naše vyhľadávacie rozhranie API.

Začneme inicializáciou databázy s niekoľkými používateľmi - aby sme mali pripravené a dostupné na testovanie:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfig.class}) @Transactional @Rollback verejná trieda JPAQuerydslIntegrationTest {@Autowired private MyUserRepository repo; private MyUser userJohn; private MyUser userTom; @ Pred public void init () {userJohn = nový MyUser (); userJohn.setFirstName ("John"); userJohn.setLastName ("Laň"); userJohn.setEmail ("[chránený e-mailom]"); userJohn.setAge (22); repo.save (userJohn); userTom = new MyUser (); userTom.setFirstName ("Tom"); userTom.setLastName ("Srnka"); userTom.setEmail ("[chránený e-mailom]"); userTom.setAge (26); repo.save (userTom); }}

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

@Test public void givenLast_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = nový MyUserPredicatesBuilder (). With ("lastName", ":", "Doe"); Iterovateľné výsledky = repo.findAll (builder.build ()); assertThat (results, containsInAnyOrder (userJohn, userTom)); }

Teraz sa pozrime, ako nájsť používateľa so zadanou hodnotou meno aj priezvisko:

@Test public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder () .with ("firstName", ":", "John"). With ("lastName", ":", "Doe" Iterovateľné výsledky = repo.findAll (builder.build ()); assertThat (results, contains (userJohn)); assertThat (výsledky, nie (obsahuje (userTom))); }

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

@Test public void givenLastAndAge_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder () .with ("lastName", ":", "Doe"). With ("age", ">", "25"); Iterovateľné výsledky = repo.findAll (builder.build ()); assertThat (results, contains (userTom)); assertThat (výsledky, nie (obsahuje (userJohn))); }

Teraz sa pozrime, ako hľadať MyUser že v skutočnosti neexistuje:

@Test public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder () .with ("firstName", ":", "Adam"). With ("lastName", ":", "Fox" Iterovateľné výsledky = repo.findAll (builder.build ()); assertThat (results, emptyIterable ()); }

Na záver - pozrime sa, ako nájsť MyUser krstné meno - ako v nasledujúcom príklade:

@Test public void givenPartialFirst_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = nový MyUserPredicatesBuilder (). With ("firstName", ":", "jo"); Iterovateľné výsledky = repo.findAll (builder.build ()); assertThat (results, contains (userJohn)); assertThat (výsledky, nie (obsahuje (userTom))); }

8. UserController

Na záver dáme všetko dohromady a zostavme rozhranie REST API.

Definujeme a UserController ktorá definuje jednoduchú metódu findAll () s "Vyhľadávanie„Parameter na odoslanie reťazca dotazu:

@Controller verejná trieda UserController {@Autowired private MyUserRepository myUserRepository; @RequestMapping (method = RequestMethod.GET, value = "/ myusers") @ResponseBody public Iterable search (@RequestParam (value = "search") String search) {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder (); if (search! = null) {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)); }} BooleanExpression exp = builder.build (); vrátiť myUserRepository.findAll (exp); }}

Tu je príklad rýchleho testu adresy URL:

// localhost: 8080 / myusers? search = priezvisko: srnka, vek> 25 rokov

A odpoveď:

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

9. Záver

Tento tretí článok sa zaoberal prvé kroky pri zostavovaní dotazovacieho jazyka pre REST API, pričom dobre využíva knižnicu Querydsl.

Implementácia je samozrejme skoro, ale dá sa ľahko vyvinúť tak, aby podporovala ďalšie operácie.

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 - Pokročilé vyhľadávacie operácie « Predchádzajúci dotazovací jazyk REST so špecifikáciami JPA Spring Data

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