JPA / Hibernate projekcije

1. Pregled

U ovom uputstvu naučit ćemo kako projicirati svojstva entiteta pomoću JPA i Hibernate.

2. Entitet

Prvo, pogledajmo entitet koji ćemo koristiti u ovom članku:

@ Entitet javne klase Proizvod {@ Id privatni dugi ID; privatni naziv niza; opis privatnog niza; kategorija privatni niz; privatna BigDecimalna jedinicaPrice; // postavljači i dobivači}

Ovo je jednostavna klasa entiteta koja predstavlja proizvod s različitim svojstvima.

3. JPA projekcije

Iako specifikacije JPA ne spominju izričito projekcije, postoje mnogi slučajevi u kojima ih nalazimo u konceptu.

Tipično, JPQL upit ima klasu entiteta kandidata. Upit prilikom izvršenja stvara objekte klase kandidata - popunjavajući sva njihova svojstva pomoću preuzetih podataka.

Ali, moguće je dohvatiti podskup svojstava entiteta, ili, to jest, a projekcija podataka stupaca.

Osim podataka iz stupaca, također možemo projicirati rezultate funkcija grupiranja.

3.1. Projekcije u jednom stupcu

Pretpostavimo da želimo navesti imena svih proizvoda. U JPQL-u to možemo učiniti uključivanjem samo datoteke Ime u Odaberi klauzula:

Upit upita = entityManager.createQuery ("odaberite ime iz proizvoda"); Popis rezultataList = query.getResultList ();

Ili, možemo učiniti isto s CriteriaBuilder:

CriteriaBuilder builder = entityManager.getCriteriaBuilder (); CriteriaQuery query = builder.createQuery (String.class); Korijenski proizvod = query.from (Product.class); query.select (product.get ("ime")); Popis rezultataList = entityManager.createQuery (upit) .getResultList ();

Jer projiciramo jedan stupac koji je slučajno tipa Niz, očekujemo da ćemo dobiti popis Nizs u rezultatu. Stoga smo klasu kandidata odredili kao Niz u createQuery () metoda.

Budući da želimo projicirati na jednom posjedu, koristili smo Query.select () metoda. Ovdje se radi o tome koju imovinu želimo, pa bismo u našem slučaju koristili Ime vlasništvo iz našeg Proizvod entitet.

Sada, pogledajmo primjer uzorka koji generiraju gornja dva upita:

Naziv proizvoda 1 Naziv proizvoda 2 Naziv proizvoda 3 Naziv proizvoda 4

Imajte na umu da da smo koristili iskaznica svojstvo u projekciji umjesto Ime, upit bi vratio popis Dugo predmeta.

3.2. Projekcije u više stupaca

Da bismo projektirali na više stupaca pomoću JPQL-a, moramo samo dodati sve potrebne stupce u Odaberi klauzula:

Upit upita = session.createQuery ("odaberite ID, ime, unitPrice iz proizvoda"); Popis rezultataList = query.getResultList ();

Ali, kada koristite a CriteriaBuilder, stvari ćemo morati učiniti malo drugačije:

CriteriaBuilder builder = session.getCriteriaBuilder (); CriteriaQuery query = builder.createQuery (Object []. Class); Korijenski proizvod = query.from (Product.class); query.multiselect (product.get ("id"), product.get ("name"), product.get ("unitPrice")); Popis rezultataList = entityManager.createQuery (upit) .getResultList ();

Ovdje, koristili smo metodu više odabrati () umjesto Odaberi(). Pomoću ove metode možemo odrediti više stavki koje ćemo odabrati.

Druga značajna promjena je upotreba Objekt[]. Kada odaberemo više stavki, upit vraća niz objekata s vrijednošću za svaku projiciranu stavku. To je slučaj i s JPQL-om.

Pogledajmo kako izgledaju podaci kad ih ispisujemo:

[1, Naziv proizvoda 1, 1,40] [2, Naziv proizvoda 2, 4,30] [3, Naziv proizvoda 3, 14,00] [4, Naziv proizvoda 4, 3,90]

Kao što vidimo, vraćeni podaci pomalo su nezgodni za obradu. Ali, srećom, možemo dobiti JPA da popuni te podatke u prilagođenu klasu.

Također, možemo koristiti CriteriaBuilder.tuple () ili CriteriaBuilder.construct () da biste dobili rezultate kao popis Korijen objekti ili objekti prilagođene klase.

3.3. Projektiranje skupnih funkcija

Osim podataka iz stupaca, ponekad bismo htjeli podatke grupirati i koristiti agregatne funkcije, na primjer računati i prosječno.

Recimo da želimo pronaći broj proizvoda u svakoj kategoriji. To možemo učiniti pomoću računati() agregatna funkcija u JPQL:

Upit upita = entityManager.createQuery ("odaberite p.category, count (p) iz grupe proizvoda p po p.category");

Ili možemo koristiti CriteriaBuilder:

CriteriaBuilder builder = entityManager.getCriteriaBuilder (); CriteriaQuery query = builder.createQuery (Object []. Class); Korijenski proizvod = query.from (Product.class); query.multiselect (product.get ("kategorija"), builder.count (proizvod)); query.groupBy (product.get ("kategorija"));

Evo, koristili smo CriteriaBuilder‘S računati() metoda.

Korištenjem bilo čega od gore navedenog stvorit će se popis nizova objekata:

[kategorija1, 2] [kategorija2, 1] [kategorija3, 1]

Osim računati(), CriteriaBuilder pruža razne druge agregatne funkcije:

  • prosj - Izračunava prosječnu vrijednost za stupac u grupi
  • maks - Izračunava maksimalnu vrijednost za stupac u grupi
  • min - Izračunava minimalnu vrijednost za stupac u grupi
  • najmanje - pronalazi najmanju vrijednost stupca (na primjer, abecedno ili prema datumu)
  • iznos - Izračunava zbroj vrijednosti stupaca u grupi

4. Hibernate projekcije

Za razliku od JPA, Hibernate pruža org.hibernate.criterion.Projection za projektiranje s a Kriteriji upit. Također pruža klasu tzv org.hibernate.criterion.Projections, tvornica za Projekcija instance.

4.1. Projekcije u jednom stupcu

Prvo, pogledajmo kako možemo projicirati jedan stupac. Upotrijebit ćemo primjer koji smo vidjeli ranije:

Kriteriji kriterija = session.createCriteria (Product.class); kriterij = kriterij.setProjection (Projections.property ("name")); 

Koristili smo Criteria.setProjection () metoda za specificiranje svojstva koje želimo u rezultatu upita. Projections.property () radi isti posao za nas kao Root.get () učinio pri navođenju stupca za odabir.

4.2. Projekcije u više stupaca

Da bismo projicirali više stupaca, prvo ćemo morati stvoriti ProjectionList. ProjectionList je posebna vrsta Projekcija koja obavija druge projekcije kako bi se omogućilo odabir više vrijednosti.

Možemo stvoriti ProjectionListkoristiti Projections.projectionList () metoda, poput prikazivanja Proizvod‘S iskaznica i Ime:

Kriteriji kriterija = session.createCriteria (Product.class); kriteriji = kriterij.setProjection (Projections.projectionList () .add (Projections.id ()) .add (Projections.property ("name")));

4.3. Projektiranje skupnih funkcija

Baš kao CriteriaBuilder, Projekcije klasa također pruža metode za agregatne funkcije.

Pogledajmo kako možemo implementirati primjer brojanja koji smo vidjeli ranije:

Kriteriji kriterija = session.createCriteria (Product.class); kriteriji = kriterij.setProjection (Projections.projectionList () .add (Projections.groupProperty ("kategorija")) .add (Projections.rowCount ()));

Važno je to napomenuti nismo izravno odredili GROUP BY u Kriteriji objekt. Pozivanje groupProperty pokreće ovo za nas.

Osim rowCount () funkcija, Projekcije također pruža agregatne funkcije koje smo vidjeli ranije.

4.4. Korištenje zamjenskog imena za projekciju

Zanimljiva značajka Hibernate Criteria API je upotreba aliasa za projekciju.

To je posebno korisno kada se koristi agregatna funkcija, jer se tada možemo pozvati na alias u Kriterij i Narudžba primjerci:

Kriteriji kriterija = session.createCriteria (Product.class); kriteriji = kriterij.setProjection (Projections.projectionList () .add (Projections.groupProperty ("kategorija")) .add (Projections.alias (Projections.rowCount (), "count")))); kriteriji.addOrder (Order.asc ("count"));

5. Zaključak

U ovom smo članku vidjeli kako projicirati svojstva entiteta pomoću JPA i Hibernate.

Važno je napomenuti da Hibernate je zastareo svoj Criteria API od verzije 5.2 nadalje u korist JPA CriteriaQuery API. Ali to je samo zato što tim hibernacije nema vremena sinkronizirati dva različita API-ja, koji uglavnom čine istu stvar.

I naravno, kod korišten u ovom članku možete pronaći na GitHubu.