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

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

• REST lekérdezési nyelv Spring Data JPA specifikációkkal (aktuális cikk) • REST Query nyelv tavaszi adatok JPA-val és Querydsl

• 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 REST API keresése / szűrése a Spring Data JPA és a Specifikációk felhasználásával.

A sorozat első cikkében elkezdtük vizsgálni a lekérdezés nyelvét - egy JPA Criteria alapú megoldással.

Í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. Felhasználó Entitás

Először - kezdjük egy egyszerűvel Felhasználó entitás a Keresési API-nkhoz:

@Entity public class User {@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; // szabványos mérőeszközök és beállítók}

3. Szűrés használatával Leírás

Most - térjünk bele egyenesen a probléma legérdekesebb részébe - az egyéni Spring Data JPA-val történő lekérdezéssel Specifikációk.

Létrehozunk egy Felhasználói specifikáció amely végrehajtja a Leírás interfész és megyünk adja át saját kényszerünkben a tényleges lekérdezés összeállításához:

public class UserSpecification végrehajtja Specification {private SearchCriteria feltételek; @Override public Predicate toPredicate (Gyökérgyökér, CriteriaQuery lekérdezés, CriteriaBuilder készítő) {if (feltételek.getOperation (). EqualsIgnoreCase (">")) {return builder.greaterThanOrEqualTo (root. Get (feltételek.getKey ()), feltételek. getValue (). toString ()); } else if (feltételek.getOperation (). equalsIgnoreCase ("<")) {return builder.lessThanOrEqualTo (root. get (feltételek.getKey ()), feltételek.getValue (). toString ()); } else if (feltételek.getOperation (). equalsIgnoreCase (":")) {if (root.get (feltételek.getKey ()). getJavaType () == String.osztály) {return builder.like (root.get ( feltételek.getKey ()), "%" + szempontok.getValue () + "%"); } else {return builder.equal (root.get (feltételek.getKey ()), feltételek.getValue ()); }} return null; }}

Ahogy látjuk - létrehozunk egy Leírás néhány egyszerű kényszer alapján amelyet a következőkben képviselünk:Keresési feltétel" osztály:

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

A Keresési feltétel a megvalósítás egy kényszer alapvető ábrázolását tartalmazza - és ezen a korláton alapul a lekérdezés felépítése:

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

Természetesen a megvalósítás leegyszerűsített és javítható; ez azonban szilárd alap a szükséges erőteljes és rugalmas műveletekhez.

4. A UserRepository

Következő - vessünk egy pillantást a UserRepository; egyszerűen kiterjesztjük a JpaSpecificationExecutor az új specifikációs API-k beszerzéséhez:

nyilvános felület A UserRepository kiterjeszti a JpaRepository, JpaSpecificationExecutor {}

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

Most - teszteljük az új keresési API-t.

Először hozzunk létre néhány felhasználót, hogy készen álljanak a teszt futtatásakor:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = {PersistenceJPAConfig.class}) @Transactional @TransactionConfiguration public class JPASpecificationsTest {@Autowired private UserRepository repository; private User userJohn; private User userTom; @A nyilvános void előtt init () {userJohn = new User (); userJohn.setFirstName ("John"); userJohn.setLastName ("Doe"); userJohn.setEmail ("[e-mail védett]"); userJohn.setAge (22); repository.save (userJohn); userTom = új felhasználó (); userTom.setFirstName ("Tom"); userTom.setLastName ("Doe"); userTom.setEmail ("[e-mail védett]"); userTom.setAge (26); repository.save (userTom); }}

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

@Test public void givenLast_whenGettingListOfUsers_thenCorrect () {UserSpecification spec = new UserSpecification (new SearchCriteria ("vezetékNév", ":", "őz")); Eredmények felsorolása = repository.findAll (spec); assertThat (userJohn, isIn (eredmények)); assertThat (userTom, isIn (eredmények)); }

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 () {UserSpecification spec1 = new UserSpecification (new SearchCriteria ("keresztnév", ":", "john")); UserSpecification spec2 = new UserSpecification (új SearchCriteria ("vezetékNév", ":", "őz")); Eredmények felsorolása = repository.findAll (Specification.where (spec1) .and (spec2)); assertThat (userJohn, isIn (eredmények)); assertThat (userTom, nem (isIn (eredmények))); }

Megjegyzés: A „hol”És„és" nak nek össze Specifikációk.

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

@Test public void givenLastAndAge_whenGettingListOfUsers_thenCorrect () {UserSpecification spec1 = new UserSpecification (new SearchCriteria ("age", ">", "25")); UserSpecification spec2 = new UserSpecification (új SearchCriteria ("vezetékNév", ":", "őz")); Eredmények felsorolása = repository.findAll (Specification.where (spec1) .and (spec2)); assertThat (userTom, isIn (eredmények)); assertThat (userJohn, nem (isIn (eredmények))); }

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

@Test public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect () {UserSpecification spec1 = new UserSpecification (new SearchCriteria ("keresztnév", ":", "Adam")); UserSpecification spec2 = new UserSpecification (új SearchCriteria ("vezetékNév", ":", "Fox")); Eredmények felsorolása = repository.findAll (Specification.where (spec1) .and (spec2)); assertThat (userJohn, nem (isIn (eredmények))); assertThat (userTom, nem (isIn (eredmények))); }

Végül - nézzük meg, hogyan lehet megtalálni a Felhasználó a keresztnévnek csak egy részét adták:

@Test public void givenPartialFirst_whenGettingListOfUsers_thenCorrect () {UserSpecification spec = new UserSpecification (new SearchCriteria ("keresztnév", ":", "jo")); Eredmények felsorolása = repository.findAll (spec); assertThat (userJohn, isIn (eredmények)); assertThat (userTom, nem (isIn (eredmények))); }

6. Össze Specifikációk

Következő - vessünk egy pillantást a szokásunk ötvözésére Specifikációk többféle kényszer használatához és több szempont szerinti szűréshez.

Építőt fogunk megvalósítani - UserSpecificationsBuilder - könnyen és gördülékenyen kombinálni Specifikációk:

public class UserSpecificationsBuilder {private final List paraméterek; public UserSpecificationsBuilder () {params = new ArrayList (); } public UserSpecificationsBuilder with (String key, String operation, Object value) {params.add (new SearchCriteria (kulcs, művelet, érték)); adja vissza ezt; } public Specification build () {if (params.size () == 0) {return null; } Lista specifikációi = params.stream () .map (UserSpecification :: new) .collect (Collectors.toList ()); Specifikáció eredménye = specs.get (0); for (int i = 1; i <params.size (); i ++) {eredmény = params.get (i) .isOrPredicate ()? Specification.where (eredmény) .vagy (specs.get (i)): Specification.where (eredmény) .and (specs.get (i)); } visszatérési eredmény; }}

7. UserController

Végül - használjuk ezt az új perzisztencia keresési / szűrési funkciót és állítsa be a REST API-t - létrehozásával a UserController egy egyszerűvel keresés művelet:

@Controller public class UserController {@Autowired private UserRepository repo; @RequestMapping (method = RequestMethod.GET, value = "/ users") @ResponseBody public List search (@RequestParam (value = "search") String search) {UserSpecificationsBuilder builder = new UserSpecificationsBuilder (); Minta minta = Minta.kompile ("(\ w +?) (: |) (\ w +?),"); Matcher matcher = minta.matcher (keresés + ","); míg (matcher.find ()) {builder.with (matcher.group (1), matcher.group (2), matcher.group (3)); } Specifikáció spec = builder.build (); return repo.findAll (spec); }}

Vegye figyelembe, hogy más, nem angol nyelvű rendszerek támogatásához a Minta objektum megváltoztatható, mint:

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

Itt van egy teszt URL példa az API kipróbálására:

// localhost: 8080 / users? 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}]

Mivel a kereséseket egy "," osztja a mi Minta Például a keresési kifejezések nem tartalmazhatják ezt a karaktert. A minta szintén nem egyezik a szóközzel.

Ha vesszőket tartalmazó értékeket akarunk keresni, akkor fontolóra vehetjük egy másik elválasztó, például a „;” használatát.

Egy másik lehetőség az lenne, ha megváltoztatnánk a mintát úgy, hogy értékeket keressünk az idézőjelek között, majd levesszük ezeket a keresési kifejezésből:

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

8. Következtetés

Ez az oktatóanyag egy egyszerű megvalósítást ismertetett, amely egy erőteljes REST lekérdezési nyelv alapja lehet. Jól alkalmaztuk a Spring Data Specifications-t annak biztosítására, hogy távol tartsuk az API-t a tartománytól és lehetősége van számos más típusú művelet kezelésére.

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 Lekérdezés nyelve a Spring Data JPA-val és a Querydsl-lel « Előző REST lekérdezési nyelv tavaszi és JPA kritériumokkal