Spørring Av Jpa-Enheter med JPQL og Innfødt SQL

Eksempelprogram

kodebitene som er omtalt i artikkelen, er hentet fra Java-kildefilene som brukes i eksempelprogrammet som følger med artikkelen. Ser gjennom eksempelarkivet, kan du legge merke til at dette er en enkel Webapplikasjon basert På Java Servlet OG Java Persistence API-teknologiene. For enkelhet bruker den ikke enterprise beans, som utsteder JPQL-spørringer direkte fra servlets. Det betyr imidlertid ikke at DU ikke vil kunne bruke JPQL-spørringene som er diskutert her i enterprise beans—du kan definere JPQL-spørringer i Noen Java EE-komponenter.

Figur 1 illustrerer utvalgsenhetene struktur. Som du kan se, inneholder den et sett med enheter relatert til hverandre med relasjoner av forskjellige typer. En slik forgreningsstruktur er nødvendig for å illustrere bruken AV jpql join-spørringer diskutert i Definerende JPQL Joins-delen senere i artikkelen.

Figur 1 Relasjoner mellom enhetene som brukes i eksempelprogrammet

for en detaljert instruksjon om hvordan du konfigurerer og deretter starter eksempelappen, kan du se readme.txt-fil i rotkatalogen i eksempelarkivet.

Bruke JPQL I Java ee-applikasjoner

hvis du har litt praktisk erfaring med databaser, har du mest sannsynlig allerede fått føttene våte MED SQL, standardverktøyet som tilbyr et sett med uttalelser for å få tilgang til og manipulere informasjon i relasjonsdatabaser. FAKTISK er det mange likheter mellom JPQL og SQL. Begge brukes til å få tilgang til og manipulere databasedata, i det lange løp. Og begge bruker nonprocedural uttalelser-kommandoer anerkjent av en spesiell tolk. VIDERE ER JPQL lik SQL i sin syntaks.

hovedforskjellen MELLOM JPQL og SQL ligger i at den tidligere omhandler jpa-enheter, mens sistnevnte handler direkte med relasjonsdata. Som Java-utvikler kan du også være interessert i å lære AT bruk AV JPQL, i motsetning TIL SQL/JDBC, eliminerer behovet for at DU bruker JDBC API fra Java-koden din.

JPQL lar deg definere spørringer ved hjelp av ett av følgende tre setninger: VELG, OPPDATER eller SLETT. Det er interessant å merke seg at EntityManager API-grensesnittet tilbyr metoder som også kan brukes til å utføre hente, oppdatere og slette operasjoner over enheter. Spesielt er disse finne, slå sammen og fjerne metoder. Bruken av disse metodene er imidlertid vanligvis begrenset til en enkelt enhetsforekomst, med mindre cascading trer i kraft, selvfølgelig. I MOTSETNING HAR JPQL-setninger ikke en slik begrensning – du kan definere masseoppdatering og slette operasjoner over sett med enheter, og definere spørringer som returnerer sett med enhetsforekomster.

for å utstede EN jpql-spørring fra Java-koden din, må du bruke passende metoder For EntityManager API OG Query API, og utføre følgende generelle trinn:

  • 1. Få en forekomst Av EntityManager, ved hjelp av injeksjon eller eksplisitt gjennom en EntityManagerFactory forekomst.
  • 2. Opprett En forekomst Av Spørring ved å påkalle en passende EntityManager metode, for eksempel createQuery.
  • 3. Angi en spørringsparameter eller parametere, hvis noen, ved hjelp av en passende Spørringens setParameter-metode.
  • 4. Hvis nødvendig, angi maksimalt antall forekomster for å hente og / eller angi plasseringen av første instans for å hente, ved hjelp av setMaxResults og / eller setFirstResult Spørring metoder.
  • 5. Angi om nødvendig et leverandørspesifikt hint ved hjelp av setHint-Spørr-metoden.
  • 6. Hvis nødvendig, angi flush-modus for spørringen kjøring med setFlushMode Spørring metode, overstyre entity manager flush-modus.
  • 7. Kjør spørringen ved hjelp av en passende Spørringsmetode: getsingleresultat eller getResultList. Når det gjelder en oppdatering eller sletting, må du imidlertid bruke executeUpdate-metoden, som returnerer antall enhetsforekomster som er oppdatert eller slettet.

den fullstendige listen Over EntityManager-grensesnittmetodene, samt API-grensesnittmetodene For SPØRRING, finnes I Enterprise JavaBeans 3.0-Spesifikasjonen: Java Persistence API-dokument, som er en del AV JSR-220.

Nå som du har en grov ide om hvordan du kan opprette OG deretter utstede EN JPQL-spørring, vil du kanskje se noen praktiske eksempler. Følgende kodefragment er hentet fra en servlet doGet-metode som bruker EN jpql-spørring til å hente informasjon om alle kundene som er lagret i den underliggende relasjonstabellen som er knyttet Til Kundeenheten som er angitt i spørringen.

  ... @PersistenceUnit private EntityManagerFactory emf; public void doGet( ... EntityManager em = emf.createEntityManager(); PrintWriter out = response.getWriter(); List<Customer> arr_cust = (List<Customer>)em.createQuery("SELECT c FROM Customer c") .getResultList(); out.println("List of all customers: "+""); Iterator i = arr_cust.iterator(); Customer cust; while (i.hasNext()) { cust = (Customer) i.next(); out.println(cust.getCust_id()+""); out.println(cust.getCust_name()+""); out.println(cust.getEmail()+""); out.println(cust.getPhone()+""); out.println("----------------" + ""); } ... 

av spesiell interesse her er createQuery-metoden For EntityManager-forekomsten og getResultList-metoden for spørringsforekomsten. EntityManager createQuery brukes til å opprette spørringsforekomsten hvis getResultList-metode brukes til å utføre jpql-spørringen som sendes til createQuery som parameter. Som du kanskje skjønner, Returnerer Spørringens getResultList-metode resultatet av en spørring som En Liste der elementene i dette eksemplet er kastet til Å skrive Kunde.

Hvis du trenger å hente et enkelt resultat, Tilbyr Query API-grensesnittet getsingleresult-metoden, som vist i følgende eksempel. Vær imidlertid oppmerksom på at bruk av getSingleResult vil føre til et unntak hvis du får flere resultater tilbake.

dette eksemplet illustrerer også Bruken av Spørr-setParameter-metoden der Du kan binde et argument til en spørringsparameter. Med setParameter kan du binde både navngitte og posisjonsparametere. Her binder du imidlertid en navngitt parameter.

  ... Integer cust_id =2; Customer cust = (Customer)em.createQuery("SELECT c FROM Customer c WHERE c.cust_id=:cust_id") .setParameter("cust_id", cust_id) .getSingleResult(); out.println("Customer with id "+cust.getCust_id()+" is: "+ cust.getCust_name()+""); ... 

det er interessant å merke seg at bruk AV EN SELECT JPQL-setning ikke er den eneste måten å gå når det gjelder å hente en enkelt enhetsforekomst. Alternativt kan du bruke EntityManager ‘ s find-metode, som lar deg hente en enkelt enhetsforekomst basert på enhetens id som er sendt inn som parameter.

i noen situasjoner må du kanskje hente bare noe informasjon fra målenheten forekomst eller forekomster, definere EN jpql spørring mot en bestemt enhet felt eller felt. Dette er hva den ovennevnte kodebiten vil se ut, hvis du bare trenger å hente verdien av cust_name-feltet i Kundeenhetens forekomst, spørres her:

  ... Integer cust_id =2; String cust_name = (String)em.createQuery("SELECT c.cust_name FROM Customer c WHERE c.cust_id=:cust_id") .setParameter("cust_id", cust_id) .getSingleResult(); out.println("Customer with id "+cust_id+" is: "+cust_name+""); ... 

På Samme måte, for å få hele listen over kundenes navn, kan du bruke følgende kode:

  ... List<String> arr_cust_name = (List<String>)em.createQuery("SELECT c.cust_name FROM Customer c") .getResultList(); out.println("List of all customers: "+"<br/>"); Iterator i = arr_cust_name.iterator(); String cust_name; while (i.hasNext()) { cust_name = (String) i.next(); out.println(cust_name+"<br/>"); } ... 

Når du Går tilbake TIL SQL, kan du huske at select-listen over EN SQL-spørring kan bestå av flere felt fra tabellen eller tabellene som er angitt I FROM-setningsdelen. I JPQL kan du også bruke en sammensatt select list, velge dataene bare fra enhetens interessefelt. I så fall må du imidlertid opprette klassen som du vil kaste spørringsresultatet til. I følgende avsnitt vil du se et eksempel PÅ EN jpql join-spørring hvis utvalgsliste består av feltene avledet fra mer enn en enhet.

Definere jpql Joins

SOM SQL lar JPQL deg definere sammenføyningsspørringer. I SQL definerer du imidlertid vanligvis en sammenføyning som kombinerer poster fra to eller flere tabeller og / eller visninger, inkludert bare obligatoriske felt fra disse tabellene og visningene i select-listen i sammenføyningsspørringen. I motsetning til dette inneholder select-listen over en jpql join-spørring vanligvis en enkelt enhet eller til og med et enkelt enhetsfelt. Årsaken til dette ligger i NATUREN TIL JPA-teknologien. Når du får en enhetsforekomst, kan du deretter navigere til de relaterte forekomstene ved hjelp av tilsvarende getter-metoder. Denne tilnærmingen gjør det unødvendig for deg å definere en spørring som vil returnere alle relaterte enhet forekomster av interesse samtidig.

hvis du for eksempel vil få informasjon om ordrer sammen med linjeelementene I SQL, må du definere en sammenføyningsspørring på tabellene purchaseOrders og orderLineItems, og angi feltene fra begge tabellene i utvalgslisten for spørringen. Når DU bruker JPQL, kan du imidlertid definere en spørring bare Over PurchaseOrder-enheten, og deretter navigere til tilsvarende OrderLineItem-forekomster ved hjelp Av Purchaseorders getOrderLineItems-metode etter behov. I dette eksemplet vil du kanskje definere EN jpql-spørring over Enhetene PurchaseOrder og OrderLineItem bare hvis du trenger å filtrere Hentet Purchaseorderforekomster basert på en betingelse eller betingelser som brukes På OrderLineItem.

følgende kodebit viser et eksempel PÅ jpql join-spørring i aksjon. For bedre å forstå hvordan de involverte enhetene er relatert til hverandre, kan Du gå tilbake Til Figur 1 vist i Eksempelapplikasjonsdelen tidligere i artikkelen.

  ... Double max = (Double) em.createQuery("SELECT MAX(p.price) FROM PurchaseOrder o JOIN o.orderLineItems l JOIN l.product p JOIN p.supplier s WHERE s.sup_name = 'Tortuga Trading'") .getSingleResult(); out.println("The highest price for an ordered product supplied by Tortuga Trading: "+ max + "<br/>"); ... 

I eksemplet ovenfor bruker DU MAKS aggregat-funksjonen I select-klausulen i join-spørringen for å bestemme det høyeste prisproduktet, av de som Har blitt levert av Tortuga Trading og har blitt bestilt minst en gang.

en mer vanlig situasjon er imidlertid når du må beregne den totale prisen på de bestilte produktene, som er levert av en bestemt leverandør. DETTE er hvor SUM aggregatfunksjonen kan komme til nytte. I SQL kan en slik sammenføyningsspørring se slik ut:

  SELECT SUM(p.price*l.quantity) FROM purchaseorders o JOIN orderlineitems l ON o.pono=l.pono JOIN products p ON l.prod_id=p.prod_id JOIN suppliers s ON p.sup_id=s.sup_id WHERE sup_name ='Tortuga Trading'; 

DESSVERRE TILLATER IKKE SUM-funksjonen som brukes I JPQL at du sender et aritmetisk uttrykk som argumentet. Hva dette betyr i praksis er at du ikke vil kunne passere p. price * l. quantity som argumentet TIL JPQL SUM. Det er imidlertid måter å omgå dette problemet på. I eksemplet nedenfor definerer du klasse LineItemSum som konstruktøren brukes i listen velg spørringen, tar p. pris og l. antall som parametere. Hva LineItemSum-konstruktøren gjør er å multiplisere p. pris med l. mengde, og lagre resultatet til sin rslt-klassevariabel. Deretter kan du iterere Gjennom Lineitemsumlisten hentet av spørringen, summere verdiene til Lineitemsums rslt-variabel. Følgende utdrag viser hvordan alt dette kan implementeres i kode:

  package jpqlexample.servlets; ... class LineItemSum { private Double price; private Integer quantity; private Double rslt; public LineItemSum (Double price, Integer quantity){ this.rslt = quantity*price; } public Double getRslt () { return this.rslt; } public void setRslt (Double rslt) { this.rslt = rslt; } } public class JpqlJoinsServlet extends HttpServlet { ... public void doGet( ... List<LineItemSum> arr = (List<LineItemSum>)em.createQuery ("SELECT NEW jpqlexample.servlets.LineItemSum(p.price, l.quantity) FROM PurchaseOrder o JOIN o.orderLineItems l JOIN l.product p JOIN p.supplier s WHERE s.sup_name = 'Tortuga Trading'") .getResultList(); Iterator i = arr.iterator(); LineItemSum lineItemSum; Double sum = 0.0; while (i.hasNext()) { lineItemSum = (LineItemSum) i.next(); sum = sum + lineItemSum.getRslt(); } out.println("The total cost of the ordered products supplied by Tortuga Trading: "+ sum + "<br/>"); } } 

eksemplet ovenfor illustrerer blant annet hvordan du kan bruke en egendefinert Java-klasse, ikke en entitetsklasse, I jpql-spørringens utvalgsliste som inneholder feltene avledet fra mer enn en enhet, og kaster resultatet av spørringen til den klassen. I de fleste tilfeller må du imidlertid håndtere spørsmål som mottar en forekomst eller en liste over forekomster av en bestemt enhet.

Hentet Enhetsforekomster Og Gjeldende Vedvarende Kontekst

spørringsresultatene i artikkelseksemplene så langt er ganske enkelt skrevet ut. I virkelige applikasjoner må du kanskje utføre noen videre operasjoner på spørringsresultatene. Du må for eksempel oppdatere de hentede forekomstene og deretter fortsette dem tilbake til databasen. Dette reiser spørsmålet: er forekomstene blir hentet av EN JPQL spørring klar til å bli videre behandlet av programmet, eller noen ekstra trinn er nødvendig for å gjøre dem klar for det? Spesielt ville det være interessant å lære i hvilken stat, om den nåværende utholdenhetskonteksten, hentet enhet forekomster er.

hvis du har litt erfaring Med Java Utholdenhet, bør du vite hva en utholdenhet kontekst er. En vedvarende kontekst er et sett med enhetsforekomster som administreres av EntityManager-forekomsten som er knyttet til den konteksten. I eksemplene ovenfor brukte Du createQuery-metoden For entitymanager til å opprette En forekomst Av Spørring for å utføre EN jpql-spørring. EntityManager API inneholder faktisk mer enn tjue metoder for å administrere livssyklusen til enhetsforekomster, kontrollere transaksjoner og opprette forekomster Av Spørring hvis metoder deretter brukes til å utføre spørringen som er angitt og hente spørringsresultatet.

når det gjelder en vedvarende kontekst, kan en enhetsforekomst være i en av følgende fire tilstander: ny, administrert, frakoblet eller fjernet. Ved hjelp av en passende EntityManager metode, kan du endre tilstanden til en bestemt enhet forekomst etter behov. Det er imidlertid interessant å merke seg at bare forekomster i administrert tilstand synkroniseres til databasen, når det oppstår flushing til databasen. For å være presis synkroniseres også enhetsforekomstene i fjernet tilstand, noe som betyr at databasepostene som svarer til disse forekomstene, fjernes fra databasen.

derimot synkroniseres ikke forekomster i den nye eller frittstående tilstanden til databasen. Hvis du for eksempel oppretter en Ny PurchaseOrder-forekomst og deretter aktiverer entitymanager flush-metoden, vises ikke en annen post i purchaseOrders-tabellen Som PurchaseOrder-enheten er tilordnet til. Dette skyldes at den nye PurchaseOrder-forekomsten ikke er knyttet til utholdenhetskonteksten. Her er hva koden kan se ut:

  ... em.getTransaction().begin(); Customer cust = (Customer) em.find(Customer.class, 1); PurchaseOrder ord = new PurchaseOrder(); ord.setOrder_date(new Date()); ord.setCustomer(cust); em.getTransaction().commit(); ... 

for å løse problemet må du aktivere entitymanager ‘ s vedvarer metode for den nye PurchaseOrder-forekomsten før du starter flush, som vist i følgende eksempel:

  ... em.getTransaction().begin(); Customer cust = (Customer) em.find(Customer.class, 1); PurchaseOrder ord = new PurchaseOrder(); ord.setOrder_date(new Date()); ord.setCustomer(cust); em.persist(ord); em.getTransaction().commit(); ... 

du kan også legge til Den nyopprettede PurchaseOrder-forekomsten i listen over ordrene som er knyttet til kundeforekomsten, og erstatte vedvarer-operasjonen med følgende:

  cust.getPurchaseOrders().add(ord); 

ovennevnte diskusjon om enhetsforekomststater fører oss til det interessante spørsmålet om hvorvidt enhetsforekomstene som hentes av EN JPQL-spørring, blir automatisk administrert, eller du må passe på å eksplisitt angi at tilstanden skal administreres. I HENHOLD TIL jpa-spesifikasjonen, uansett hvordan du henter enheter—enten Det er EntityManager ‘ s søkemetode eller en spørring—de er automatisk knyttet til gjeldende utholdenhet kontekst. Dette betyr at enhetsforekomster hentet av EN JPQL-spørring blir automatisk administrert. Du kan for eksempel endre verdien for feltet for en hentet forekomst og deretter synkronisere endringen til databasen ved å aktivere entitymanager ‘ s flush-metode eller begå gjeldende transaksjon. Du trenger ikke å bekymre deg om tilstanden i tilfeller knyttet til hentet forekomster enten. Faktum er at første gang du åpner en tilknyttet forekomst, blir den administrert automatisk. Her er et enkelt eksempel som viser hvordan alt dette fungerer i praksis:

  ... em.getTransaction().begin(); PurchaseOrder ord = (PurchaseOrder)em.createQuery("SELECT o FROM PurchaseOrder o WHERE o.pono = 1") .getSingleResult(); List<OrderLineItem> items = ord.getOrderLineItems(); Integer qnt = items.get(0).getQuantity(); out.println("Quantity of the first item : "+ qnt +"<br/>"); items.get(0).setQuantity(qnt+1); qnt = items.get(0).getQuantity(); em.getTransaction().commit(); out.println("Quantity of the first item : "+ qnt +"<br/>"); ... 

Vær oppmerksom på at du ikke aktiverer metoden vedvarer for Den hentede PurchaseOrder-forekomsten, og heller ikke for at Den relaterte OrderLineItem-forekomsten endres her. Til tross for dette vil endringene som gjøres i første linjepost i bestillingen, bli videreført til databasen ved å begå transaksjonen. Dette skjer fordi både de hentede enhetsforekomstene og deres tilknytninger automatisk knyttes til gjeldende vedvarende kontekst. Som nevnt tidligere blir de tidligere administrert når de hentes, og sistnevnte er knyttet til konteksten når du får tilgang til dem.

i noen situasjoner vil du kanskje at tilknytninger skal knyttes til konteksten ved kjøring av spørringen, i stedet for ved første tilgang. Det er her A HENTE DELTA kommer til nytte. Si, du vil få alle ordrene som tilhører en bestemt kunde, ved å hente den kundeforekomsten. Denne tilnærmingen garanterer at du håndterer kundeordrer som er tilgjengelige på tidspunktet for spørringen. Hvis for eksempel en ny ordre legges til i en annen kontekst og deretter synkroniseres til databasen før du først får tilgang til ordrelisten som er knyttet til kundeforekomsten hentet, vil du ikke se denne endringen før du oppdaterer tilstanden til kundeforekomsten fra databasen. I den følgende kodebiten bruker du join-spørringen som returnerer kundeforekomsten som cust_id er 1, og henter PurchaseOrder-forekomstene som er knyttet Til Kundeforekomsten som hentes.

  ... Customer cust = (Customer)em.createQuery("SELECT DISTINCT c FROM Customer c LEFT JOIN FETCH c.purchaseOrders WHERE c.cust_id=1") .getSingleResult(); ... List<PurchaseOrder> orders = cust.getPurchaseOrders(); ... 

Ettersom Den ikke er en del av det eksplisitte spørringsresultatet, hentes Instansene For PurchaseOrder-enheten som er knyttet til Kundeforekomsten her, også og knyttes til gjeldende vedvarende kontekst ved kjøring av spørringen.

Utnytte Innfødte SQL-Spørringer

det er interessant å merke seg at DU ikke er begrenset TIL JPQL når du definerer spørringer som skal utføres med Query API. Du kan bli overrasket over å høre at EntityManager API tilbyr metoder for å lage forekomster Av Spørring for å utføre innfødte SQL-setninger. Det viktigste å forstå om innfødte SQL-spørringer som er opprettet med EntityManager-metoder, er at DE, som JPQL-spørringer, returnerer entitetsforekomster, i stedet for databasetabellposter. Her er et enkelt eksempel på en dynamisk innfødt SQL-spørring:

  ... List<Customer> customers = (List<Customer>)em.createNativeQuery ("SELECT * FROM customers", jpqlexample.entities.Customer.class) .getResultList(); Iterator i = customers.iterator(); Customer cust; out.println("Customers: " + "<br/>"); while (i.hasNext()) { cust = (Customer) i.next(); out.println(cust.getCust_name() +"<br/>"); } ... 

JPQL utvikler seg fortsatt, og har ikke mange av de viktige funksjonene som er tilgjengelige i SQL. I Den Definerende jpql Joins tidligere delen så du et eksempel PÅ JPQLS ufullstendighet: du måtte gjøre mye arbeid alene fordi JPQLS SUMAGGREGATFUNKSJON ikke kan ta et aritmetisk uttrykk som parameter. I motsetning HAR SQL SUM-funksjonen ikke en slik begrensning. Så dette er et godt eksempel på hvor erstatning AV JPQL med innfødt SQL kan være effektiv. Følgende kode illustrerer hvordan du kan forenkle ting i dette eksemplet ved å velge innfødt SQL over JPQL:

  ... String sup_name ="Tortuga Trading"; BigDecimal sum = (List)em.createNativeQuery("SELECT SUM(p.price*l.quantity) FROM orders o JOIN orderlineitems l ON o.pono=l.pono JOIN products p ON l.prod_id=p.prod_id JOIN suppliers s ON p.sup_id=s.sup_id WHERE sup_name =?1") .setParameter(1, sup_name) .getSingleResult(); out.println("The total cost of the ordered products supplied by Tortuga Trading: " + sum +"<br/>"); ... 

eksemplet ovenfor illustrerer blant annet at du kan binde argumenter til innfødte spørringsparametere. Spesielt kan du binde argumenter til posisjonsparametere på samme måte som om DU hadde å gjøre med EN JPQL-spørring.

den største ulempen ved innfødte spørringer er kompleksiteten av resultatbinding. I eksemplet gir spørringen et enkelt resultat av en enkel type, og dermed unngår dette problemet. I praksis må du imidlertid ofte håndtere et resultatsett av en kompleks type. I dette tilfellet må du deklarere en enhet som du kan tilordne den opprinnelige spørringen til, eller definere et komplekst resultatsett som er tilordnet til flere enheter eller til en blanding av enheter og skalarresultater.

Ved Hjelp Av Lagrede Prosedyrer

En annen ulempe med innfødte spørringer er At Java-koden din blir direkte avhengig av den underliggende databasestrukturen. Skulle du endre den underliggende strukturen, må du justere de innfødte spørringene i servlets og/eller andre applikasjonskomponenter, og måtte kompilere og omplassere disse komponentene etter det. Hvis du vil omgå dette problemet, mens du fortsatt bruker opprinnelige spørringer, kan du dra nytte av lagrede prosedyrer, flytte komplekse SQL-spørringer til programmer som er lagret og utført i databasen, og deretter ringe de lagrede programmene i stedet for å ringe direkte til de underliggende tabellene. Hva dette betyr i praksis er at lagrede prosedyrer kan spare deg bryet med å håndtere de underliggende tabellene direkte fra spørringene som er hardkodet I Java-koden. Fordelen med denne tilnærmingen er at du i de fleste tilfeller ikke trenger å endre Java-koden for å følge endringene i den underliggende databasestrukturen. I stedet vil bare de lagrede prosedyrene trenge å fikse.

Når du Vender tilbake til eksemplet som er omtalt i forrige del, kan du flytte den komplekse sammenføyningsspørringen som brukes der, til en lagret funksjon, opprettet som følger:

  CREATE OR REPLACE FUNCTION sum_total(supplier VARCHAR2) RETURN NUMBER AS sup_sum NUMBER; BEGIN SELECT SUM(p.price*l.quantity) INTO sup_sum FROM orders o JOIN orderlineitems l ON o.pono=l.pono JOIN products p ON l.prod_id=p.prod_id JOIN suppliers s ON p.sup_id=s.sup_id WHERE sup_name = supplier; RETURN sup_sum; END; / 

dette forenkler den opprinnelige spørringen som brukes I Java-koden, og fjerner avhengigheten fra de underliggende tabellene:

  ... String sup_name ="Tortuga Trading"; BigDecimal sum = (BigDecimal)em.createNativeQuery("SELECT sum_total(?1) FROM DUAL") .setParameter(1, sup_name) .getSingleResult(); out.println("The total cost of the ordered products supplied by Tortuga Trading: " + sum +"<br/>"); ... 

Konklusjon

SOM du lærte i denne artikkelen, ER JPQL et kraftig verktøy når DET gjelder å få tilgang til relasjonsdata fra Java-applikasjoner som bruker Java-Utholdenhet. Med JPQL, i motsetning TIL MED SQL/JDBC, definerer du spørringer over JPA-enheter som er kartlagt til underliggende databasetabeller i stedet for å spørre disse tabellene direkte, og dermed håndtere et lag med abstraksjon som skjuler databasedetaljer fra forretningslogikklaget. DU lærte også AT JPQL ikke er det eneste alternativet når DET gjelder å lage spørringer over JPA-enheter—i noen situasjoner er det mer praktisk å bruke innfødte SQL-spørringer.