JPA - JPQL

Ce chapitre vous présente JPQL et son fonctionnement avec les unités de persistance. Dans ce chapitre, les exemples suivent la même hiérarchie de packages, que nous avons utilisée dans le chapitre précédent comme suit:

Langage de requête de persistance Java

JPQL est le langage de requête de persistance Java défini dans la spécification JPA. Il est utilisé pour créer des requêtes sur des entités à stocker dans une base de données relationnelle. JPQL est développé sur la base de la syntaxe SQL. Mais cela n'affectera pas directement la base de données.

JPQL peut récupérer des informations ou des données à l'aide de la clause SELECT, peut effectuer des mises à jour en masse à l'aide des clauses UPDATE et DELETE. L'API EntityManager.createQuery () prendra en charge le langage d'interrogation.

Structure de la requête

La syntaxe JPQL est très similaire à la syntaxe de SQL. Avoir une syntaxe similaire à SQL est un avantage car SQL est un langage de requête structuré simple et de nombreux développeurs l'utilisent dans des applications. SQL fonctionne directement avec les tables, les enregistrements et les champs de base de données relationnelle, tandis que JPQL fonctionne avec les classes et les instances Java.

Par exemple, une requête JPQL peut récupérer un objet entité plutôt qu'un jeu de résultats de champ à partir de la base de données, comme avec SQL. La structure de requête JPQL comme suit.

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

La structure des requêtes JPQL DELETE et UPDATE est plus simple comme suit.

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

Fonctions scalaires et agrégées

Les fonctions scalaires renvoient les valeurs résultantes basées sur les valeurs d'entrée. Les fonctions d'agrégation retournent les valeurs résultantes en calculant les valeurs d'entrée.

Suivez le même exemple de gestion des employés utilisé dans les chapitres précédents. Ici, nous allons passer en revue les classes de service en utilisant les fonctions scalaires et agrégées de JPQL.

Supposons que la table jpadb.employee contienne les enregistrements suivants.

Eid Ename Un salaire Degré
1201 Gopal 40000 Directeur technique
1202 Manisha 40000 Lecteur d'épreuves
1203 Masthanvali 40000 Rédacteur technique
1204 Satish 30000 Rédacteur technique
1205 Krishna 30000 Rédacteur technique
1206 Kiran 35 000 Lecteur d'épreuves

Créez une classe nommée ScalarandAggregateFunctions.java en dessous de com.tutorialspoint.eclipselink.service paquet comme suit.

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);
   }
}

Après la compilation et l'exécution du programme ci-dessus, vous obtiendrez la sortie dans le panneau de la console d'Eclipse IDE comme suit:

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

Entre, et, comme des mots clés

«Entre», «Et» et «J'aime» sont les principaux mots-clés de JPQL. Ces mots clés sont utilisés après la clause Where dans une requête.

Créez une classe nommée BetweenAndLikeFunctions.java en dessous de com.tutorialspoint.eclipselink.service paquet comme suit:

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( ));
      }
   }
}

Après la compilation et l'exécution du programme ci-dessus, vous obtiendrez la sortie dans le panneau de la console d'Eclipse IDE comme suit:

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

Commande

Pour commander les enregistrements en JPQL, nous utilisons la clause ORDER BY. L'utilisation de cette clause est identique à l'utilisation en SQL, mais elle concerne les entités. Suivez la commande par exemple.

Créez une classe Ordering.java sous com.tutorialspoint.eclipselink.service paquet comme suit:

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( ));
      }
   }
}

Après la compilation et l'exécution du programme ci-dessus, vous obtiendrez la sortie dans le panneau de la console d'Eclipse IDE comme suit:

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

Requêtes nommées

Une annotation @NamedQuery est définie comme une requête avec une chaîne de requête non modifiable prédéfinie. Au lieu de requêtes dynamiques, l'utilisation de requêtes nommées peut améliorer l'organisation du code en séparant les chaînes de requête JPQL de POJO. Il transmet également les paramètres de requête plutôt que d'incorporer dynamiquement des littéraux dans la chaîne de requête et aboutit à des requêtes plus efficaces.

Tout d'abord, ajoutez l'annotation @NamedQuery à la classe d'entité Employee nommée Employee.java en dessous de com.tutorialspoint.eclipselink.entity paquet comme suit:

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 + "]";
   }
}

Créez une classe nommée NamedQueries.java en dessous de com.tutorialspoint.eclipselink.service paquet comme suit:

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( ));
      }
   }
}

Après la compilation et l'exécution du programme ci-dessus, vous obtiendrez la sortie dans le panneau de la console d'Eclipse IDE comme suit:

Employee ID :1204	 Employee Name :Satish

Après avoir ajouté toutes les classes ci-dessus, la hiérarchie des packages est affichée comme suit:

Chargement impatient et paresseux

Le concept principal de JPA est de faire une copie de la base de données dans la mémoire cache. Lors des transactions avec la base de données, cela affectera d'abord les données en double et seulement quand elles sont validées à l'aide du gestionnaire d'entités, les modifications sont effectuées dans la base de données.

Il existe deux manières de récupérer des enregistrements de la base de données: la récupération rapide et la récupération différée.

Envie d'aller chercher

Récupération de l'ensemble de l'enregistrement tout en trouvant l'enregistrement à l'aide de la clé primaire.

Récupération paresseuse

Il vérifie la disponibilité de le notifie avec la clé primaire si elle existe. Ensuite, si vous appelez l'une des méthodes getter de cette entité, elle récupère le tout.

Mais la récupération paresseuse est possible lorsque vous essayez de récupérer l'enregistrement pour la première fois. De cette façon, une copie de l'ensemble de l'enregistrement est déjà stockée dans la mémoire cache. En termes de performances, la récupération paresseuse est préférable.