JPA - JPQL

Questo capitolo ti parla di JPQL e di come funziona con le unità di persistenza. In questo capitolo, gli esempi seguono la stessa gerarchia dei pacchetti, che abbiamo usato nel capitolo precedente come segue:

Linguaggio Java Persistence Query

JPQL è Java Persistence Query Language definito nella specifica JPA. Viene utilizzato per creare query su entità da archiviare in un database relazionale. JPQL è sviluppato sulla base della sintassi SQL. Ma non influenzerà direttamente il database.

JPQL può recuperare informazioni o dati utilizzando la clausola SELECT, può eseguire aggiornamenti in blocco utilizzando la clausola UPDATE e la clausola DELETE. L'API EntityManager.createQuery () supporterà il linguaggio di query.

Struttura della query

La sintassi JPQL è molto simile alla sintassi di SQL. Avere una sintassi simile a SQL è un vantaggio perché SQL è un semplice linguaggio di query strutturato e molti sviluppatori lo utilizzano nelle applicazioni. SQL funziona direttamente con tabelle, record e campi del database relazionale, mentre JPQL funziona con classi e istanze Java.

Ad esempio, una query JPQL può recuperare un oggetto entità anziché un set di risultati di campo dal database, come con SQL. La struttura della query JPQL come segue.

SELECT ... FROM ...
[WHERE ...]
[GROUP BY ... [HAVING ...]]
[ORDER BY ...]

La struttura delle query JPQL DELETE e UPDATE è più semplice come segue.

DELETE FROM ... [WHERE ...]
 
UPDATE ... SET ... [WHERE ...]

Funzioni scalari e aggregate

Le funzioni scalari restituiscono i valori risultanti in base ai valori di input. Le funzioni aggregate restituiscono i valori risultanti calcolando i valori di input.

Segui lo stesso esempio di gestione dei dipendenti utilizzato nei capitoli precedenti. Qui esamineremo le classi di servizio utilizzando funzioni scalari e aggregate di JPQL.

Supponiamo che la tabella jpadb.employee contenga i seguenti record.

Eid Ename Stipendio Deg
1201 Gopal 40000 Responsabile tecnico
1202 Manisha 40000 Lettore di bozze
1203 Masthanvali 40000 Scrittore tecnico
1204 Satish 30000 Scrittore tecnico
1205 Krishna 30000 Scrittore tecnico
1206 Kiran 35000 Lettore di bozze

Crea una classe denominata ScalarandAggregateFunctions.java sotto com.tutorialspoint.eclipselink.service pacchetto come segue.

package com.tutorialspoint.eclipselink.service;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class ScalarandAggregateFunctions {
   public static void main( String[ ] args ) {
   
      EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
      EntityManager entitymanager = emfactory.createEntityManager();

      //Scalar function
      Query query = entitymanager.
      createQuery("Select UPPER(e.ename) from Employee e");
      List<String> list = query.getResultList();

      for(String e:list) {
         System.out.println("Employee NAME :"+e);
      }
      
      //Aggregate function
      Query query1 = entitymanager.createQuery("Select MAX(e.salary) from Employee e");
      Double result = (Double) query1.getSingleResult();
      System.out.println("Max Employee Salary :" + result);
   }
}

Dopo la compilazione e l'esecuzione del programma di cui sopra, otterrai l'output nel pannello della console dell'IDE Eclipse come segue:

Employee NAME :GOPAL
Employee NAME :MANISHA
Employee NAME :MASTHANVALI
Employee NAME :SATISH
Employee NAME :KRISHNA
Employee NAME :KIRAN
ax Employee Salary :40000.0

Tra e, come parole chiave

"Between", "And" e "Like" sono le parole chiave principali di JPQL. Queste parole chiave vengono utilizzate dopo la clausola Where in una query.

Crea una classe denominata BetweenAndLikeFunctions.java sotto com.tutorialspoint.eclipselink.service pacchetto come segue:

package com.tutorialspoint.eclipselink.service;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;

public class BetweenAndLikeFunctions {
   public static void main( String[ ] args ) {
   
      EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
      EntityManager entitymanager = emfactory.createEntityManager();
      
      //Between
      Query query = entitymanager.createQuery( "Select e " + "from Employee e " + "where e.salary " + "Between 30000 and 40000" );
      
      List<Employee> list=(List<Employee>)query.getResultList( );

      for( Employee e:list ){
         System.out.print("Employee ID :" + e.getEid( ));
         System.out.println("\t Employee salary :" + e.getSalary( ));
      }

      //Like
      Query query1 = entitymanager.createQuery("Select e " + "from Employee e " + "where e.ename LIKE 'M%'");
      
      List<Employee> list1=(List<Employee>)query1.getResultList( );
      
      for( Employee e:list1 ) {
         System.out.print("Employee ID :"+e.getEid( ));
         System.out.println("\t Employee name :"+e.getEname( ));
      }
   }
}

Dopo la compilazione e l'esecuzione del programma di cui sopra, otterrai l'output nel pannello della console dell'IDE Eclipse come segue:

Employee ID :1201	 Employee salary :40000.0
Employee ID :1202	 Employee salary :40000.0
Employee ID :1203	 Employee salary :40000.0
Employee ID :1204	 Employee salary :30000.0
Employee ID :1205	 Employee salary :30000.0
Employee ID :1206	 Employee salary :35000.0

Employee ID :1202	 Employee name :Manisha
Employee ID :1203	 Employee name :Masthanvali

Ordinazione

Per ordinare i record in JPQL usiamo la clausola ORDER BY. L'utilizzo di questa clausola è lo stesso dell'uso in SQL, ma si occupa di entità. Segui l'Ordine per esempio.

Crea una classe Ordering.java sotto com.tutorialspoint.eclipselink.service pacchetto come segue:

package com.tutorialspoint.eclipselink.service;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;

public class Ordering {

   public static void main( String[ ] args ) {
      EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
      EntityManager entitymanager = emfactory.createEntityManager();
      
      //Between
      Query query = entitymanager.createQuery( "Select e " + "from Employee e " + "ORDER BY e.ename ASC" );

      List<Employee> list = (List<Employee>)query.getResultList( );

      for( Employee e:list ) {
         System.out.print("Employee ID :" + e.getEid( ));
         System.out.println("\t Employee Name :" + e.getEname( ));
      }
   }
}

Dopo la compilazione e l'esecuzione del programma di cui sopra, otterrai l'output nel pannello della console dell'IDE Eclipse come segue:

Employee ID :1201	 Employee Name :Gopal
Employee ID :1206	 Employee Name :Kiran
Employee ID :1205	 Employee Name :Krishna
Employee ID :1202	 Employee Name :Manisha
Employee ID :1203	 Employee Name :Masthanvali
Employee ID :1204	 Employee Name :Satish

Query con nome

Un'annotazione @NamedQuery è definita come una query con una stringa di query non modificabile predefinita. Invece di query dinamiche, l'utilizzo di query denominate può migliorare l'organizzazione del codice separando le stringhe di query JPQL da POJO. Passa anche i parametri della query anziché incorporare dinamicamente i valori letterali nella stringa di query e produce query più efficienti.

Prima di tutto, aggiungi l'annotazione @NamedQuery alla classe di entità Employee denominata Employee.java sotto com.tutorialspoint.eclipselink.entity pacchetto come segue:

package com.tutorialspoint.eclipselink.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@Table
@NamedQuery(query = "Select e from Employee e where e.eid = :id", name = "find employee by id")

public class Employee {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO) 	
   
   private int eid;
   private String ename;
   private double salary;
   private String deg;
   
   public Employee(int eid, String ename, double salary, String deg) {
      super( );
      this.eid = eid;
      this.ename = ename;
      this.salary = salary;
      this.deg = deg;
   }
   
   public Employee( ) {
      super();
   }

   public int getEid( ) {
      return eid;
   }
   
   public void setEid(int eid) {
      this.eid = eid;
   }

   public String getEname( ) {
      return ename;
   }
   
   public void setEname(String ename) {
      this.ename = ename;
   }

   public double getSalary( ) {
      return salary;
   }
   
   public void setSalary(double salary) {
      this.salary = salary;
   }

   public String getDeg( ) {
      return deg;
   }
   
   public void setDeg(String deg) {
      this.deg = deg;
   }
   
   @Override
   public String toString() {
      return "Employee [eid=" + eid + ", ename=" + ename + ", salary=" + salary + ", deg=" + deg + "]";
   }
}

Crea una classe denominata NamedQueries.java sotto com.tutorialspoint.eclipselink.service pacchetto come segue:

package com.tutorialspoint.eclipselink.service;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;

public class NamedQueries {
   public static void main( String[ ] args ) {
   
      EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
      EntityManager entitymanager = emfactory.createEntityManager();
      Query query = entitymanager.createNamedQuery("find employee by id");
      
      query.setParameter("id", 1204);
      List<Employee> list = query.getResultList( );
      
      for( Employee e:list ){
         System.out.print("Employee ID :" + e.getEid( ));
         System.out.println("\t Employee Name :" + e.getEname( ));
      }
   }
}

Dopo la compilazione e l'esecuzione del programma di cui sopra, otterrai l'output nel pannello della console dell'IDE Eclipse come segue:

Employee ID :1204	 Employee Name :Satish

Dopo aver aggiunto tutte le classi di cui sopra, la gerarchia del pacchetto viene mostrata come segue:

Caricamento desideroso e pigro

Il concetto principale di JPA è creare una copia duplicata del database nella memoria cache. Durante la transazione con il database, prima avrà effetto sui dati duplicati e solo quando viene eseguito il commit utilizzando Entity Manager, le modifiche vengono effettuate nel database.

Esistono due modi per recuperare i record dal database: recupero desideroso e recupero lento.

Desideroso di recupero

Recupero dell'intero record mentre si trova il record utilizzando la chiave primaria.

Recupero pigro

Controlla la disponibilità di notifica con chiave primaria se esiste. Successivamente, se chiami uno dei metodi getter di quell'entità, viene recuperato l'intero.

Ma il recupero pigro è possibile quando si tenta di recuperare il record per la prima volta. In questo modo, una copia dell'intero record è già archiviata nella memoria cache. Per quanto riguarda le prestazioni, è preferibile il recupero pigro.