JPA lekérdezési paraméterek használata

1. Bemutatkozás

A JPA segítségével nem nehéz lekérdezéseket készíteni néha azonban elfelejtjük az egyszerű dolgokat, amelyek hatalmas változást hoznak.

Ezek egyike a JPA lekérdezési paraméterei, és erről fogunk beszélni.

2. Mik a lekérdezési paraméterek?

Kezdjük azzal, hogy elmagyarázzuk, melyek a lekérdezési paraméterek.

A lekérdezési paraméterek a paraméterezett lekérdezések összeállításának és végrehajtásának módját jelentik. Tehát ahelyett, hogy:

SELECT * FROM alkalmazottak e WHERE e.emp_number = '123';

Tennénk:

SELECT * FROM alkalmazottak e WHERE e.emp_number =?;

A JDBC által készített utasítás használatával be kell állítanunk a paramétert a lekérdezés végrehajtása előtt:

pStatement.setString (1, 123);

3. Miért használjunk lekérdezési paramétereket?

A lekérdezési paraméterek használata helyett választhattunk volna literálokat is, de ez nem az ajánlott módszer, ahogyan most látni fogjuk.

Írjuk át az előző lekérdezést, hogy az alkalmazottak bekerüljenek emp_number a JPA API használatával, de egy paraméter helyett egy literált fogunk használni, hogy világosan szemléltessük a helyzetet:

String empNumber = "A123"; TypedQuery lekérdezés = em.createQuery ("SELECT e FROM Employee e WHERE e.empNumber = '" + empNumber + "'", Employee.class); Alkalmazott alkalmazott = query.getSingleResult ();

Ennek a megközelítésnek van néhány hátránya:

  • A beágyazott paraméterek biztonsági kockázatot jelentenek, és kiszolgáltatottá tesznek minket a JPQL injekciós támadások ellen. A várt érték helyett a támadó bármilyen váratlan és esetleg veszélyes JPQL kifejezést beadhat
  • Az általunk használt JPA megvalósítástól és alkalmazásunk heurisztikájától függően a lekérdezési gyorsítótár kimerülhet. Egy új lekérdezés felépülhet, lefordítható és gyorsítótárba kerül minden alkalommal, amikor minden egyes új értéknél / paraméternél használjuk. Legalábbis nem lesz hatékony, és váratlan dologhoz is vezethet OutOfMemoryError

4. JPA lekérdezési paraméterek

A JDBC által készített utasításparaméterekhez hasonlóan a JPA két különböző módszert határoz meg a paraméterezett lekérdezések megírásához:

  • Pozíciós paraméterek
  • Megnevezett paraméterek

Használhatunk helyzeti vagy megnevezett paramétereket is, de nem keverhetjük őket ugyanazon lekérdezésen belül.

4.1. Pozíciós paraméterek

A helyzetparaméterek használata az egyik módja a korábban felsorolt ​​problémák elkerülésének.

Lássuk, hogyan írnánk ilyen lekérdezést a helyzeti paraméterek segítségével:

TypedQuery lekérdezés = em.createQuery ("SELECT e FROM Employee e WHERE e.empNumber =? 1", Employee.class); Karakterlánc empNumber = "A123"; Alkalmazott alkalmazott = query.setParameter (1, empNumber) .getSingleResult ();

Amint az előző példán belül láthattuk, deklaráljuk ezeket a paramétereket a lekérdezésen belül egy kérdőjel beírásával, amelyet egy pozitív egész szám követ. Kezdjük 1 és haladjon előre, minden alkalommal eggyel növelve.

Ugyanazt a paramétert többször is használhatjuk ugyanazon lekérdezésen belül, ami ezeket a paramétereket jobban hasonlítja a megnevezett paraméterekhez.

A paraméterek számozása nagyon hasznos funkció, mivel javítja a használhatóságot, az olvashatóságot és a karbantartást.

Érdemes ezt megemlíteni a helyzeti paraméterek kötését natív SQL lekérdezések is támogatják.

4.2. Gyűjtemény által értékelt pozícióparaméterek

Amint azt korábban említettük, használhatunk gyűjtemény által értékelt paramétereket is:

TypedQuery lekérdezés = entitásManager.createQuery ("SELECT e FROM Employee e WHERE e.empNumber IN (? 1)", Employee.class); List empNumbers = Arrays.asList ("A123", "A124"); Alkalmazottak listája = query.setParameter (1, empNumbers) .getResultList ();

4.3. Elnevezett paraméterek

A megnevezett paraméterek meglehetősen hasonlóak a helyzeti paraméterekhez; ezek használatával azonban kifejezettebbé tesszük a paramétereket, és a lekérdezés olvashatóbbá válik:

TypedQuery lekérdezés = em.createQuery ("SELECT e FROM Employee e WHERE e.empNumber =: szám", Employee.class); String empNumber = "A123"; Alkalmazott alkalmazott = query.setParameter ("szám", empNumber) .getSingleResult ();

Az előző minta lekérdezés megegyezik az elsővel, de már használtuk :szám, egy megnevezett paraméter helyett ?1.

Láthatjuk, hogy a paramétert kettősponttal deklaráltuk, amelyet egy karakterlánc-azonosító (JPQL azonosító) követett, amely a futás közben beállítandó tényleges érték helyőrzője. A lekérdezés végrehajtása előtt meg kell adni a paramétert vagy paramétereket a setParameter módszer.

Egy érdekes dolog megjegyezni, hogy a TypedQuery támogatja a módszer láncolását ami akkor válik nagyon hasznosá, ha több paramétert kell beállítani.

Folytassuk, és hozzuk létre az előző lekérdezés variációját két megnevezett paraméter segítségével a módszer láncolatának szemléltetésére:

TypedQuery lekérdezés = em.createQuery ("SELECT e FROM Employee e WHERE e.name =: név ÉS e.age =: empAge", Employee.class); String empName = "John Doe"; int empAge = 55; Alkalmazottak listája = lekérdezés .setParameter ("név", empName) .setParameter ("empAge", empAge) .getResultList ();

Itt visszakeresünk minden alkalmazottat, akinek a neve és kora van. Amint jól látjuk és számíthatunk rá, lekérdezéseket is készíthetünk velük több paraméter és annyi előfordulásuk, amennyi szükséges.

Ha valamilyen oknál fogva ugyanazt a paramétert kell használnunk sokszor ugyanazon a lekérdezésen belül, akkor csak egyszer kell beállítanunk a „setParameter”Módszer. Futás közben a megadott értékek helyettesítik a paraméter minden előfordulását.

Végül érdemes megemlíteni ezt a Java Persistence API specifikáció nem írja elő a megnevezett paraméterek natív lekérdezések támogatását. Még akkor is, ha egyes megvalósítások, például a Hibernate, támogatják, figyelembe kell vennünk, hogy ha mégis használjuk, a lekérdezés nem lesz annyira hordozható.

4.4. Gyűjtemény által értékelt elnevezett paraméterek

Az érthetőség kedvéért mutassuk be, hogy ez hogyan működik a gyűjtemény által értékelt paraméterekkel:

TypedQuery lekérdezés = entitásManager.createQuery ("SELECT e FROM Employee e WHERE e.empNumber IN (: számok)", Employee.class); List empNumbers = Arrays.asList ("A123", "A124"); Az alkalmazottak listája = query.setParameter ("számok", empNumbers) .getResultList ();

Mint láthatjuk, a helyzetparaméterekhez hasonló módon működik.

5. Kritériumok lekérdezési paraméterei

A JPA lekérdezés a JPA Criteria API használatával építhető fel, amelyet a Hibernate hivatalos dokumentációja részletesen elmagyaráz.

Az ilyen típusú lekérdezésekben a paramétereket objektumok használatával nevek vagy indexek helyett képviseljük.

Készítsük el ugyanazt a lekérdezést újra, de ezúttal a Criteria API segítségével mutassuk be, hogyan kell kezelni a lekérdezési paramétereket a kezelés során CriteriaQuery:

CriteriaBuilder cb = em.getCriteriaBuilder (); CriteriaQuery cQuery = cb.createQuery (Employee.class); C gyökér = cQuery.from (Employee.class); ParameterExpression paramEmpNumber = cb.parameter (String.class); cQuery.select (c) .where (cb.equal (c.get (Employee_.empNumber), paramEmpNumber)); TypedQuery lekérdezés = em.createQuery (cQuery); String empNumber = "A123"; query.setParameter (paramEmpNumber, empNumber); Munkavállalói alkalmazott = query.getResultList ();

Ennél a típusú lekérdezésnél a paraméter mechanikája kissé eltér, mivel paraméterobjektumot használunk, de lényegében nincs különbség.

Az előző példán belül láthatjuk a Munkavállaló_ osztály. Ezt az osztályt a Hibernate metamodell-generátorral hoztuk létre. Ezek az összetevők a statikus JPA metamodell részét képezik, amely lehetővé teszi a kritérium-lekérdezések erősen tipizált módon történő felépítését.

6. Következtetés

Ebben a cikkben a lekérdezések létrehozásának mechanikájára összpontosítottunk JPA lekérdezési paraméterek vagy bemeneti paraméterek felhasználásával.

Megtudtuk, hogy kétféle lekérdezési paraméterünk van, helyzeti és megnevezett. Rajtunk múlik, hogy melyik felel meg legjobban a céljainknak.

Érdemes megjegyezni azt is, hogy az összes lekérdezési paraméternek egyértékűnek kell lennie, kivéve ban ben kifejezések. Mert ban ben kifejezéseket, használhatunk gyűjtemény által értékelt bemeneti paramétereket, például tömböket vagy Listas az előző példákon belül.

Az oktatóanyag forráskódja a szokásos módon elérhető a GitHubon.