Typy dotazov JPA
1. Prehľad
V tomto tutoriáli si rozoberieme rôzne typy dotazov JPA. Ďalej sa zameriame na porovnanie rozdielov medzi nimi a na rozšírenie kladov a záporov každého z nich.
2. Inštalácia
Najskôr definujme UserEntity triedy, ktorú použijeme pre všetky príklady v tomto článku:
@Table (name = "users") @Entity public class UserEntity {@Id private Long id; súkromné meno reťazca; // Štandardný konštruktor, getre a setre. }
Existujú tri základné typy dotazov JPA:
- Dopyt, napísaný v syntaxi Java Persistence Query Language (JPQL)
- NativeQuery, napísané jednoduchou syntaxou SQL
- Criteria API Query, zostavené programovo pomocou rôznych metód
Poďme ich preskúmať.
3. Dopyt
A Dopyt má podobnú syntax ako SQL a všeobecne sa používa na vykonávanie operácií CRUD:
public UserEntity getUserByIdWithPlainQuery (Long id) {Query jpqlQuery = getEntityManager (). createQuery ("SELECT u FROM UserEntity u WHERE u.id =: id"); jpqlQuery.setParameter ("id", id); return (UserEntity) jpqlQuery.getSingleResult (); }
Toto Dopyt získa zodpovedajúci záznam z používateľov tabuľky a tiež ju mapuje na UserEntity objekt.
Existujú dve ďalšie Dopyt podtypy:
- TypedQuery
- NamedQuery
Uvidíme ich v akcii.
3.1. TypedQuery
Musíme venovať pozornosť návrat vyhlásenie v našom predchádzajúcom príklade. JPA nemôže odvodiť, čo Dopyt Výsledný typ bude, a ako výsledok budeme musieť obsadiť.
Ale, JPA poskytuje špeciál Dopyt subtyp známy ako a TypedQuery.Toto je vždy preferované, ak vieme svoje Dopyt typ výsledku vopred. Vďaka tomu je náš kód oveľa spoľahlivejší a ľahšie testovateľný.
Pozrime sa a TypedQuery alternatíva v porovnaní s našim prvým príkladom:
public UserEntity getUserByIdWithTypedQuery (Long id) {TypedQuery typedQuery = getEntityManager (). createQuery ("SELECT u FROM UserEntity u WHERE u.id =: id", UserEntity.class); typedQuery.setParameter ("id", id); návrat typedQuery.getSingleResult (); }
Tadiaľto, Zadarmo máme silnejšie písanie, vyhnúť sa možným výnimkám.
3.2. NamedQuery
Aj keď môžeme dynamicky definovať a Dopyt na konkrétnych metódach môžu nakoniec prerásť do ťažko udržiavateľného kódového základu. Čo ak by sme mohli dotazy na všeobecné použitie uchovávať na jednom centralizovanom a ľahko čitateľnom mieste?
Spoločné parlamentné zhromaždenia nás v tejto veci tiež pokryli iným Dopyt subtyp známy ako a NamedQuery.
Definujeme NamedQuery na Subjekt triedy, ktorá poskytuje centralizovaný, rýchly a ľahký spôsob čítania a hľadania SubjektSúvisiace otázky.
Všetky NamedQueries musí mať jedinečný názov.
Pozrime sa, ako môžeme pridať a NamedQuery k nášmu UserEntity trieda:
@Table (name = "users") @Entity @NamedQuery (name = "UserEntity.findByUserId", query = "SELECT u FROM UserEntity u WHERE u.id =: userId") verejná trieda UserEntity {@Id private Long id; súkromné meno reťazca; // Štandardný konštruktor, getre a setre. }
The @NamedQuery anotácia musí byť zoskupená do a @NamedQueries anotácia, ak používame Java pred verziou 8. Od verzie Java 8 môžeme jednoducho opakovať @NamedQuery anotácia na našu Subjekt trieda.
Pomocou a NamedQuery je veľmi jednoduché:
public UserEntity getUserByIdWithNamedQuery (Long id) {Dotaz namedQuery = getEntityManager (). createNamedQuery ("UserEntity.findByUserId"); namedQuery.setParameter ("userId", id); return (UserEntity) namedQuery.getSingleResult (); }
4. NativeQuery
A NativeQuery je jednoducho dotaz SQL. Tie nám umožňujú uvoľniť plný výkon našej databázy, pretože môžeme používať proprietárne funkcie, ktoré nie sú dostupné v syntaxi s obmedzením JPQL.
To má svoju cenu. Stratíme prenosnosť databázy našej aplikácie s NativeQuery pretože náš poskytovateľ JPA už nemôže získavať konkrétne podrobnosti z implementácie databázy alebo od dodávateľa.
Pozrime sa, ako používať a NativeQuery ktoré poskytujú rovnaké výsledky ako naše predchádzajúce príklady:
public UserEntity getUserByIdWithNativeQuery (Long id) {Query nativeQuery = getEntityManager (). createNativeQuery ("SELECT * FROM users WHERE id =: userId", UserEntity.class); nativeQuery.setParameter ("userId", id); return (UserEntity) nativeQuery.getSingleResult (); }
Vždy musíme zvážiť, či a NativeQuery je jediná možnosť. Väčšinou dobrý JPQL Dopyt môže splniť naše potreby a čo je najdôležitejšie, udržiavať úroveň abstrakcie od skutočnej implementácie databázy.
Použitím NativeQuery nemusí to nevyhnutne znamenať, že sa uzamkneme k jednému konkrétnemu predajcovi databázy. Nakoniec, ak naše dotazy nepoužívajú proprietárne príkazy SQL a používajú iba štandardnú syntax SQL, nemalo by to robiť problém s prepínaním poskytovateľov.
5. Kritériá API Query
Kritériá Dotazy API sú programovo zostavené, typovo bezpečné dotazy - trochu podobné syntaxe dotazov JPQL:
public UserEntity getUserByIdWithCriteriaQuery (dlhé ID) {CriteriaBuilder kritériaBuilder = getEntityManager (). getCriteriaBuilder (); CriteriaQuery kritériáQuery = kritériaBuilder.createQuery (UserEntity.class); Root userRoot = criteriaQuery.from (UserEntity.class); UserEntity queryResult = getEntityManager (). CreateQuery (criteriaQuery.select (userRoot) .where (criteriaBuilder.equal (userRoot.get ("id"), id)))) .getSingleResult (); návrat queryResult; }
Môže to byť skľučujúce použiť Kritériá Dotazy na API z prvej ruky, ale môžu byť skvelou voľbou, keď potrebujeme pridať prvky dynamického dotazu, alebo keď ich spojíme s JPA Metamodel.
6. Záver
V tomto rýchlom článku sme sa dozvedeli, čo sú dotazy JPA, spolu s ich využitím.
JPA dotazy sú skvelým spôsobom, ako abstrahovať našu obchodnú logiku z našej vrstvy prístupu k údajom, pretože sa môžeme spoľahnúť na syntax JPQL a nechať nášho poskytovateľa JPA, ktorý si vyberie, spracovať Dopyt preklad.
Celý kód uvedený v tomto článku je k dispozícii na GitHub.