REST Lekérdezés nyelve a Spring Data JPA-val és a Querydsl-lel

Ez a cikk egy sorozat része: • REST Query Language with Spring and JPA Criteria

• REST lekérdezési nyelv a Spring Data JPA specifikációkkal

• REST Query Language a Spring Data JPA-val és a Querydsl-lel (aktuális cikk) • REST Query Language - Speciális keresési műveletek

• REST Query Language - VAGY művelet végrehajtása

• REST Query Language RSQL segítségével

• REST Queryds a Querydsl webes támogatásával

1. Áttekintés

Ebben az oktatóanyagban a a REST API a Spring Data JPA és a Querydsl használatával.

A sorozat első két cikkében ugyanazt a keresési / szűrési funkciót építettük fel a JPA Criteria és a Spring Data JPA Specifications segítségével.

Így - miért egy lekérdezés nyelve? Mert - bármilyen elég komplex API esetén - az erőforrások keresése / szűrése nagyon egyszerű mezőkkel egyszerűen nem elég. A lekérdezés nyelve rugalmasabb, és lehetővé teszi, hogy szűrje le pontosan a szükséges erőforrásokat.

2. Querydsl konfiguráció

Először - nézzük meg, hogyan konfigurálhatjuk a projektünket a Querydsl használatára.

Hozzá kell adnunk a következő függőségeket pom.xml:

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

Az APT - Annotation processing tool - plugint az alábbiak szerint kell konfigurálnunk:

 com.mysema.maven apt-maven-plugin 1.1.3 folyamat cél / generált források / java com.mysema.query.apt.jpa.JPAAnnotationProcessor 

Ez generálja a Q-típusokat entitásaink számára.

3. Az MyUser Entitás

Következő - vessünk egy pillantást aMyUser”Entitás, amelyet a Keresési API-nkban használni fogunk:

@Entity public class MyUser {@Id @GeneratedValue (strategy = GenerationType.AUTO) private Long id; privát karakterlánc keresztnév; privát karakterlánc vezetéknév; privát karakterlánc e-mail; privát int kor; }

4. Egyedi Predikátum With PathBuilder

Most - hozzunk létre egy egyéni Állítmány néhány önkényes korlátozás alapján.

Használjuk PathBuilder itt az automatikusan generált Q-típusok helyett, mert az elvontabb felhasználás érdekében dinamikusan kell utakat létrehoznunk:

public class MyUserPredicate {private SearchCriteria feltételek; public BooleanExpression getPredicate () {PathBuilder entitásPath = új PathBuilder (MyUser.class, "felhasználó"); IF int érték = Integer.parseInt (feltételek.getValue (). toString ()); kapcsoló (feltételek.getOperation ()) {case ":": return path.eq (érték); case ">": return path.goe (érték); case "<": return path.loe (érték); }} else {StringPath elérési útja = entitásPath.getString (feltételek.getKey ()); if (feltételek.getOperation (). equalsIgnoreCase (":")) {return path.containsIgnoreCase (feltételek.getValue (). toString ()); }} return null; }}

Vegye figyelembe, hogy az állítmány megvalósulása milyen többféle művelettel általában foglalkozik. Ez azért van, mert a lekérdezés nyelve definíció szerint egy nyitott nyelv, ahol bármilyen mező alapján szűrhet, bármilyen támogatott művelettel.

Az ilyen típusú nyílt szűrési feltételek képviseletéhez egyszerű, de meglehetősen rugalmas megvalósítást alkalmazunk - Keresési feltétel:

public class SearchCriteria {private String kulcs; privát húr művelet; magánobjektum értéke; }

A Keresési feltétel megtartja azokat a részleteket, amelyekre korlátozást kell képviselnünk:

  • kulcs: a mező neve - például: keresztnév, kor,… Stb
  • művelet: a művelet - például: Egyenlőség, kevesebb, mint… stb
  • érték: a mező értéke - például: john, 25,… stb

5. MyUserRepository

Most - vessünk egy pillantást a mi MyUserRepository.

Szükségünk van a miénkre MyUserRepository kiterjeszteni QuerydslPredicateExecutor hogy használhassuk Jóslatok később a keresési eredmények szűréséhez:

nyilvános felület A MyUserRepository kiterjeszti a JpaRepository, QuerydslPredicateExecutor, QuerydslBinderCustomizer {@Orride default public void customize (QuerydslBindings bindings, QMyUser root) {bindings.bind (String.class) .first ((SingleValueBpression) String; kötések.kizárva (root.email); }}

Ne feledje, hogy itt a létrehozott Q-típust használjuk MyUser entitás, amelyet meg fognak nevezni QMyUser.

6. Össze Jóslatok

Következő - vessünk egy pillantást az Előrejelzések kombinálására, hogy több korlátot használjunk az eredmények szűrésében.

A következő példában - építőkkel dolgozunk - MyUserPredicatesBuilder - kombinálni Jóslatok:

public class MyUserPredicatesBuilder {privát lista paraméterek; public MyUserPredicatesBuilder () {params = new ArrayList (); } public MyUserPredicatesBuilder with (String kulcs, String művelet, Object érték) {params.add (új SearchCriteria (kulcs, művelet, érték)); adja vissza ezt; } public BooleanExpression build () {if (params.size () == 0) {return null; } Lista predikátumok = params.stream (). Map (param -> {MyUserPredicate predicate = új MyUserPredicate (param); return predicate.getPredicate ();}). Filter (Objects :: nonNull) .collect (Collectors.toList () ); BooleanExpression eredmény = Expressions.asBoolean (true) .isTrue (); for (BooleanExpression predikátum: predikátumok) {eredmény = eredmény.és (állítmány); } visszatérési eredmény; }}

7. Tesztelje a keresési lekérdezéseket

Következő - teszteljük a Keresési API-t.

Kezdjük azzal, hogy néhány felhasználóval inicializáljuk az adatbázist - hogy ezek készen állnak és tesztelésre rendelkezésre állnak:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = {PersistenceConfig.class}) @Transactional @Rollback public class JPAQuerydslIntegrationTest {@Autowired private MyUserRepository repo; saját MyUser userJohn; saját MyUser userTom; @A nyilvános void előtt init () {userJohn = new MyUser (); userJohn.setFirstName ("John"); userJohn.setLastName ("Doe"); userJohn.setEmail ("[e-mail védett]"); userJohn.setAge (22); repo.save (userJohn); userTom = new MyUser (); userTom.setFirstName ("Tom"); userTom.setLastName ("Doe"); userTom.setEmail ("[e-mail védett]"); userTom.setAge (26); repo.save (userTom); }}

Ezután nézzük meg, hogyan lehet megtalálni a felhasználókat adott vezetéknevet:

@Test public void givenLast_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder (). With ("lastName", ":", "Doe"); Megismételhető eredmények = repo.findAll (builder.build ()); assertThat (eredmények, tartalmazInAnyOrder (userJohn, userTom)); }

Most nézzük meg, hogyan lehet megtalálni a megadott felhasználót kereszt- és utónév is:

@Test public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder () .with ("firstName", ":", "John") with ("lastName", ":", "Doe"); Megismételhető eredmények = repo.findAll (builder.build ()); assertThat (eredményei tartalmazzák (userJohn)); assertThat (eredmény, nem (tartalmazza (userTom))); }

Ezután nézzük meg, hogyan lehet megtalálni a felhasználót adottval a vezetéknév és a minimális életkor

@Test public void givenLastAndAge_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder () .with ("lastName", ":", "Doe") with ("age", ">", "25"); Megismételhető eredmények = repo.findAll (builder.build ()); assertThat (eredmény, tartalmazza (userTom)); assertThat (eredmény, nem (tartalmazza (userJohn))); }

Most nézzük meg, hogyan lehet keresni MyUser hogy valójában nem létezik:

@Test public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder () .with ("firstName", ":", "Adam") with ("lastName", ":", "Fox"); Megismételhető eredmények = repo.findAll (builder.build ()); assertThat (eredmények, emptyIterable ()); }

Végül - nézzük meg, hogyan lehet megtalálni a MyUser a keresztnévnek csak egy részét adták - mint a következő példában:

@Test public void givenPartialFirst_whenGettingListOfUsers_thenCorrect () {MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder (). With ("keresztnév", ":", "jo"); Megismételhető eredmények = repo.findAll (builder.build ()); assertThat (eredményei tartalmazzák (userJohn)); assertThat (eredmény, nem (tartalmazza (userTom))); }

8. UserController

Végül rakjunk össze mindent és készítsük el a REST API-t.

Meghatározzuk a UserController amely meghatároz egy egyszerű módszert Találd meg mindet() val,-vel "keresés“A lekérdezési karakterláncban átadandó paraméter:

@Controller public class 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 (keresés! = null) {Pattern pattern = Pattern.compile ("(\ w +?) (: |) (\ w +?),"); Matcher matcher = minta.matcher (keresés + ","); míg (matcher.find ()) {builder.with (matcher.group (1), matcher.group (2), matcher.group (3)); }} BooleanExpression exp = builder.build (); return myUserRepository.findAll (exp); }}

Íme egy példa egy teszt URL-re:

// localhost: 8080 / myusers? search = lastName: őz, kor> 25

És a válasz:

[{"id": 2, "keresztnév": "tom", "vezetékNév": "őz", "e-mail": "[e-mail védett]", "kor": 26}]

9. Következtetés

Ez a harmadik cikk lefedte a REST API lekérdezési nyelvének felépítésének első lépései, jól kihasználva a Querydsl könyvtárat.

A megvalósítás természetesen korai, de könnyen fejleszthető a további műveletek támogatása érdekében.

A teljes végrehajtása cikkünk megtalálható a GitHub projektben - ez egy Maven-alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.

Következő » REST Query Language - Speciális keresési műveletek « Előző REST lekérdezési nyelv a Spring Data JPA specifikációkkal