Kevätdata JPA @Query

yleiskatsaus

Kevätdata tarjoaa monia tapoja määritellä kysely, jonka voimme suorittaa. Yksi näistä on @Query-merkintä.

tässä opetusohjelmassa osoitamme, miten @Query-merkintää käytetään kevään DATAYHTEENVEDOSSA sekä jpql: n että natiivin SQL-kyselyjen suorittamiseen.

näytämme myös, miten dynaaminen kysely rakennetaan, kun @Query-merkintä ei riitä.

Jatkoluku:

johdetut kyselymenetelmät kevään tietojen yhteisen parlamentaarisen edustajakokouksen arkistoissa

tarkastelevat kyselyn derivointimekanismia kevään tietojen yhteisessä parlamentaarisessa edustajakokouksessa.
Lue lisää →

kevään tietojen yhteinen parlamentaarinen edustajakokous @muokkaamalla merkintöjä

luo DML-ja DDL-kyselyt kevään tietoihin yhteinen parlamentaarinen edustajakokous yhdistämällä @kyselyn ja @ muokkaamalla merkintöjä
Lue lisää →

valitse kysely

määrittääksemme suoritettavan SQL: n kevään tietovarastomenetelmälle, voimme merkitä menetelmän merkinnällä @Query annotation — sen arvo-attribuutti sisältää suoritettavan JPQL: n tai SQL: n.

@Query-merkintä on etusijalla nimettyihin kyselyihin nähden, jotka on merkitty merkinnällä @NamedQuery tai määritelty orm: ssä.xml-tiedosto.

on hyvä lähestymistapa sijoittaa kyselymääritelmä juuri menetelmän yläpuolelle arkiston sisälle eikä verkkotunnusmallimme sisään nimetyiksi kyselyiksi. Arkisto on vastuussa pysyvyydestä, joten se on parempi paikka tallentaa nämä määritelmät.

2.1. Jpql

oletuksena kyselyn määrittelyssä käytetään JPQL: ää.

katsotaanpa yksinkertaista arkistomenetelmää, joka palauttaa aktiiviset Käyttäjäyksiköt tietokannasta:

@Query("SELECT u FROM User u WHERE u.status = 1")Collection<User> findAllActiveUsers();

2.2. Natiivi

Voimme käyttää myös natiivia SQL: ää kyselymme määrittelyyn. Meidän tarvitsee vain asettaa nativequery-attribuutin arvo true-arvolle ja määritellä natiivi SQL-kysely annotaation arvo-attribuutissa:

@Query( value = "SELECT * FROM USERS u WHERE u.status = 1", nativeQuery = true)Collection<User> findAllActiveUsersNative();

Määritä Järjestys kyselyssä

voimme siirtää lisäparametrin Tyyppi Sort Spring Data method-ilmoitukseen, jossa on @Query-merkintä. Se käännetään järjestyksessä lauseke, joka siirtyy tietokantaan.

3.1. Yhteisen parlamentaarisen edustajakokouksen tarjoamien ja johdettujen menetelmien lajittelu

niiden menetelmien osalta, jotka saamme ulos laatikosta, kuten findAll(lajittelu) tai ne, jotka syntyvät jäsennysmenetelmän allekirjoitusten avulla, voimme käyttää objektin ominaisuuksia vain lajittelumme määrittelyyn.:

userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));

nyt kuvitella, että haluamme lajitella pituuden nimi omaisuutta:

userRepository.findAll(Sort.by("LENGTH(name)"));

kun suoritamme yllä olevan koodin, saamme poikkeuksen:

org.kevätkehys.tieto.kartoitus.PropertyReferenceException: tyypin käyttäjälle ei löydy ominaisuuden pituutta(nimeä)!

3.2. JPQL

kun käytämme jpql: ää kyselyn määrittelyyn, niin Spring Data voi käsitellä lajittelua ilman ongelmia — meidän tarvitsee vain lisätä menetelmäparametri tyyppi lajitella:

@Query(value = "SELECT u FROM User u")List<User> findAllUsers(Sort sort);

voimme kutsua tätä menetelmää ja siirtää lajitella parametri, joka järjestää tuloksen nimi ominaisuus käyttäjäobjektin:

userRepository.findAllUsers(Sort.by("name"));

ja koska käytimme @Query-merkintää, Voimme käyttää samaa menetelmää saada lajiteltu luettelo käyttäjistä heidän nimiensä pituuden mukaan:

userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)"));

on tärkeää, että käytämme Jpasortia.turvaton () luoda eräänlainen objekti-ilmentymä.

käytettäessä:

Sort.by("LENGTH(name)");

silloin saamme täsmälleen saman poikkeuksen kuin edellä nähtiin findAll () – menetelmässä.

kun Spring Data löytää @Query-merkintää käyttävän menetelmän vaarallisen lajittelujärjestyksen, se vain liittää kyselyyn lajittelulausekkeen — se ohittaa tarkistamalla, kuuluuko järjestettävä ominaisuus verkkotunnusmalliin.

3.3. Natiivi

kun @Query-merkinnässä käytetään natiivia SQL: ää, ei ole mahdollista määritellä SQL: ää.

jos teemme, saamme poikkeusluvan:

org.kevätkehys.tieto.jpa.arkisto.kysely.InvalidJpaQueryMethodException: ei voi käyttää natiivikyselyjä, joissa on dynaaminen lajittelu ja/tai sivutus

kuten poikkeus sanoo, lajittelua ei tueta natiivikyselyissä. Virheilmoitus antaa vihjeen, että sivutus aiheuttaa myös poikkeuksen.

on kuitenkin olemassa korjaus, joka mahdollistaa sivutuksen, ja käsittelemme sitä seuraavassa osassa.

sivutus

sivutus antaa meille mahdollisuuden palauttaa vain osajoukon kokonaisesta tuloksesta sivun verran. Tämä on hyödyllistä esimerkiksi, kun selaat useita sivuja tietoa web-sivulla.

toinen sivutuksen etu on se, että palvelimelta asiakkaalle lähetettävän datan määrä on minimoitu. Kun lähetämme pienempiä tietoja, voimme yleensä nähdä suorituskyvyn paranevan.

4.1. JPQL

sivutuksen käyttäminen JPQL-kyselyn määrittelyssä on suoraviivaista:

@Query(value = "SELECT u FROM User u ORDER BY id")Page<User> findAllUsersWithPagination(Pageable pageable);

voimme siirtää PageRequest parametri saada sivun tietoja.

sivutus on myös tuettu natiivikyselyihin, mutta vaatii hieman lisätyötä.

4.2. Natiivi

voimme mahdollistaa sivutuksen natiivikyselyihin ilmoittamalla ylimääräisen attribuutin countQuery.

tämä Määrittää suoritettavan SQL: n laskemaan rivien määrän koko tuloksessa:

@Query( value = "SELECT * FROM Users ORDER BY id", countQuery = "SELECT count(*) FROM Users", nativeQuery = true)Page<User> findAllUsersWithPagination(Pageable pageable);

4.3. Spring Data JPA-versiot ennen 2.0.4

yllä oleva ratkaisu natiivikyselyihin toimii hyvin Spring Data JPA-versioissa 2.0.4 ja sitä uudemmissa.

ennen kyseistä versiota, kun yritämme suorittaa tällaisen kyselyn, saamme saman poikkeuksen, jonka kuvasimme edellisessä lajitteluosassa.

voimme voittaa tämän lisäämällä kyselyymme lisäparametrin sivutusta varten:

@Query( value = "SELECT * FROM Users ORDER BY id \n-- #pageable\n", countQuery = "SELECT count(*) FROM Users", nativeQuery = true)Page<User> findAllUsersWithPagination(Pageable pageable);

yllä olevassa esimerkissä lisätään ”\n – #pageable\n ” sivutusparametrin paikkamerkiksi. Tämä kertoo Spring Data JPA miten jäsentää kyselyn ja pistää pageable parametri. Tämä ratkaisu toimii H2-tietokantaan.

olemme käsitelleet, kuinka luoda yksinkertaisia select-kyselyjä JPQL: n ja natiivin SQL: n kautta. Seuraavaksi näytämme, miten lisäparametrit määritellään.

indeksoidut Kyselyparametrit

on kaksi mahdollista tapaa, joilla voimme siirtää metodiparametrit kyselyymme: indeksoidut ja nimetyt parametrit.

tässä osiossa käsitellään indeksoituja parametreja.

5.1. JPQL

jpql: n indeksoitujen parametrien osalta Jousiaineisto siirtää metodiparametrit kyselylle samassa järjestyksessä kuin ne näkyvät menetelmäilmoituksessa:

@Query("SELECT u FROM User u WHERE u.status = ?1")User findUserByStatus(Integer status);@Query("SELECT u FROM User u WHERE u.status = ?1 and u.name = ?2")User findUserByStatusAndName(Integer status, String name);

yllä olevissa kyselyissä tilamenetelmäparametri annetaan kyselyparametrille indeksillä 1 ja nimimenetelmäparametri kyselyparametrille indeksillä 2.

5.2. Natiivi

indeksoidut parametrit natiivikyselyille toimivat täsmälleen samalla tavalla kuin JPQL: lle:

@Query( value = "SELECT * FROM Users u WHERE u.status = ?1", nativeQuery = true)User findUserByStatusNative(Integer status);

seuraavassa osassa, näytämme erilainen lähestymistapa: kulkee parametrit nimen kautta.

nimetyt parametrit

voimme myös siirtää metodin parametrit kyselyyn nimettyjen parametrien avulla. Määrittelemme nämä käyttämällä @ Param-merkintää arkiston menetelmäilmoituksen sisällä.

jokaisella @Param-merkinnällä merkityllä parametrilla on oltava arvomerkkijono, joka vastaa vastaavaa jpql-tai SQL query-parametrin nimeä. Nimetyillä parametreilla varustettu kysely on helpompi lukea ja se on vähemmän virhealtis, jos kyselyä on muokattava uudelleen.

6.1. JPQL

kuten edellä mainittiin, käytämme @Param-merkintää menetelmäilmoituksessa sovittaaksemme jpql: n nimen määrittelemät parametrit menetelmäilmoituksen parametreihin:

@Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")User findUserByStatusAndNameNamedParams( @Param("status") Integer status, @Param("name") String name);

huomaa, että edellä mainitussa esimerkissä määrittelimme SQL-kyselyn ja Metodin parametreillemme samat nimet, mutta sitä ei tarvita niin kauan kuin arvomerkkijonot ovat samat:

@Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")User findUserByUserStatusAndUserName(@Param("status") Integer userStatus, @Param("name") String userName);

6.2. Native

native-kyselyn määritelmässä ei ole eroa siinä, miten siirrämme parametrin nimen kautta kyselylle verrattuna jpql: ään-käytämme @ Param-merkintää:

@Query(value = "SELECT * FROM Users u WHERE u.status = :status and u.name = :name", nativeQuery = true)User findUserByStatusAndNameNamedParamsNative( @Param("status") Integer status, @Param("name") String name);

7. Collection parametri

tarkastellaan tapausta, jossa jpql-tai SQL-kyselymme where-lauseke sisältää in (tai ei in) – avainsanan:

SELECT u FROM User u WHERE u.name IN :names

tässä tapauksessa voidaan määritellä kyselytapa, joka ottaa keräämisen parametrina:

@Query(value = "SELECT u FROM User u WHERE u.name IN :names")List<User> findUserByNameList(@Param("names") Collection<String> names);

koska parametri on kokoelma, sitä voidaan käyttää List, HashSet, jne.

seuraavaksi näytetään, miten tietoja muokataan @Modifying-merkinnällä.

Päivityskyselyt @ muokkaamalla

voimme käyttää @Query-merkintää muuttaaksemme tietokannan tilaa lisäämällä @ – muokkausmerkinnän arkistoon.

8.1. Jpql

aineistoa muuttavalla arkistomenetelmällä on kaksi eroa select-kyselyyn verrattuna-siinä on @ – Muokkausmerkintä ja JPQL-kyselyssä käytetään tietysti päivityksen sijaan Selectiä:

@Modifying@Query("update User u set u.status = :status where u.name = :name")int updateUserSetStatusForName(@Param("status") Integer status, @Param("name") String name);

palautusarvo määrittää, kuinka monta riviä kyselyn suoritus päivitettiin. Sekä indeksoituja että nimettyjä parametreja voidaan käyttää päivityskyselyissä.

8.2. Natiivi

voimme muokata tietokannan tilaa myös natiivikyselyllä. Meidän tarvitsee vain lisätä @muokkaaminen huomautus:

@Modifying@Query(value = "update Users u set u.status = ? where u.name = ?", nativeQuery = true)int updateUserSetStatusForNameNative(Integer status, String name);

8.3. Insertit

insert-toiminnon suorittamiseksi meidän on sekä käytettävä @ – muokkausta että käytettävä natiivikyselyä, koska insertti ei ole osa JPA-rajapintaa:

@Modifying@Query( value = "insert into Users (name, age, email, status) values (:name, :age, :email, :status)", nativeQuery = true)void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("status") Integer status, @Param("email") String email);

dynaaminen kysely

usein törmäämme tarpeeseen rakentaa SQL-lausekkeita, jotka perustuvat ehtoihin tai tietokokonaisuuksiin, joiden arvot tunnetaan vain suorituksen aikana. Niissä tapauksissa emme voi käyttää staattista kyselyä.

9.1. Esimerkki dynaamisesta kyselystä

esimerkiksi, kuvitellaan tilanne, jossa meidän täytyy valita kaikki käyttäjät, joiden sähköposti on kuin yksi joukosta määritelty runtime-email1, email2,…, emailn:

SELECT u FROM User u WHERE u.email LIKE '%email1%' or u.email LIKE '%email2%' ... or u.email LIKE '%emailn%'

koska joukko on dynaamisesti rakennettu, emme voi tietää käännösaikaan, kuinka monta samanlaista lauseketta lisätään.

tässä tapauksessa emme voi käyttää vain @Query-merkintää, koska emme voi antaa staattista SQL-lausetta.

sen sijaan, ottamalla käyttöön mukautetun komposiittivaraston, voimme laajentaa perus-JpaRepository toiminnallisuutta ja tarjota Oman logiikkamme dynaamisen kyselyn rakentamiseen. Katsotaanpa, miten tämä tehdään.

9.2. Mukautetut arkistot ja JPA-kriteerien API

onneksi Jousi tarjoaa tavan laajentaa base-arkistoa käyttämällä mukautettuja fragmenttirajapintoja. Voimme sitten yhdistää ne yhteen ja luoda komposiittivaraston.

aloitamme luomalla mukautetun fragmenttiliittymän:

public interface UserRepositoryCustom { List<User> findUserByEmails(Set<String> emails);}

ja sitten toteutamme sen:

public class UserRepositoryCustomImpl implements UserRepositoryCustom { @PersistenceContext private EntityManager entityManager; @Override public List<User> findUserByEmails(Set<String> emails) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<User> query = cb.createQuery(User.class); Root<User> user = query.from(User.class); Path<String> emailPath = user.get("email"); List<Predicate> predicates = new ArrayList<>(); for (String email : emails) { predicates.add(cb.like(emailPath, email)); } query.select(user) .where(cb.or(predicates.toArray(new Predicate))); return entityManager.createQuery(query) .getResultList(); }}

kuten yllä on esitetty, hyödynsimme yhteisen edustajakokouksen KRITEERIRAJAPINTAA dynaamisen kyselymme luomiseksi.

myös impl-postfix on sisällytettävä luokan nimeen. Kevät etsii UserRepositoryCustom-toteutuksen nimellä UserRepositoryCustomImpl. Koska fragmentit eivät itsessään ole arkistoja, Spring luottaa tähän mekanismiin löytääkseen fragmentin toteutuksen.

9.3. Laajennetaan olemassa olevaa arkistoa

huomaa, että kaikki hakumenetelmät jaksosta 2 osioon 7 ovat Userrepositorissa.

so, now we ’ ll integrate our fragment by extending the new interface in the UserRepository:

public interface UserRepository extends JpaRepository<User, Integer>, UserRepositoryCustom { // query methods from section 2 - section 7}

9.4. Käyttämällä arkistoa

ja lopuksi voimme kutsua dynaamista kyselytapaamme:

Set<String> emails = new HashSet<>();// filling the set with any number of itemsuserRepository.findUserByEmails(emails);

olemme onnistuneet luomaan komposiittivaraston ja kutsuneet mukautetun menetelmämme.

johtopäätös

tässä artikkelissa käsittelimme useita tapoja määritellä kyselyt kevään tietojen yhteisen parlamentaarisen edustajakokouksen arkistointimenetelmissä @Query-merkinnällä.

opimme myös toteuttamaan mukautetun arkiston ja luomaan dynaamisen kyselyn.

kuten aina, tässä artikkelissa käytetyt täydelliset koodiesimerkit löytyvät GitHubista.

Vastaa

Sähköpostiosoitettasi ei julkaista.