SlideShare une entreprise Scribd logo
1  sur  63
La solution de persistance en Java:
                JPA
          Sadok Ben Yahia
Motivation
      L’Objet est devenu le style fondamental de la programmation

UML

                Conception
                                                      O2, EyeBD
                        Comment faire
                        correspondance
                        entre O/R              Base de données OO



   Développement

                                         ???
Langage orienté
objet: java c# c++...

                                                                    4
Solution ?
ORM : Object / Relational Mapping



        encapsulation


          attribut




                                        SQL


                                    ligne




                                              5
ORM c’est quoi?
                  Le mapping objet relationnel crée une illusion
                  d’une BDOO à partir d’une BDR

 Donc on peut bénéficier de l’orienté objet et gérer
 une BD relationnelle d’une façon transparente.           public class Obj {
                                                           private int id;
                                                           private String name;

             Id          name                                 public Obj(){
                                                          }
             ..          ..
                                                            public Obj(String name) {
             …           ..                                   this.name = name;
             …           ..                                 }
                                                            public void setId(int i) {
                                                              id = i;
                                                            }
                                                          ….
                                                          }
Il existe plusieurs Framework de mapping
objet/relationnel : Java Persistance API, TopLink, Java
Data Object, Hibernate, Object Relational Bridge…

                                                                                         7
Un peu d’histoire …

• Entity Beans EJB 1.0 -> 2.1
  – Complexité
     • EJB2.x "entity" et les EJB2.x "session » :
         – un EJB2.x "entity" est l'image d'une ligne de table de BD
         – EJB2.x "session" un objet utilisé pour implémenter les couches
           [metier], [dao] d'une architecture multi-couches
     • La courbe d’apprentissage trop prononcée
     • Modèle de programmation non-intuitif (ne sont utilisables
       qu'au sein de conteneurs EJB)
  – Performance
     • Le coût pour effectuer certaines requêtes était hors de
       proportions,

                                                                            5
Un peu d’histoire …
•   Les équipes IT se sont de plus en plus tournés vers d’autres produits sur le
    marché:
•   Hibernate
     – Le plus répandu dans la communauté présentement. Toutefois, la responsabilité de
       compatibilité avec différents serveurs d’application revient à la communauté.
•   JDO
     – Bien que JDO soit un standard, appuyé par la JSR 243 (JDO 2.0), cette technologie a reçu bien
       peu d’appui.
•   Produits commerciaux (ex. TopLink)
     – API propriétaires, onéreux, non-standard …

•   Ces trois solutions fonctionnent globalement suivant les mêmes principes :
     – Des fichiers de mapping pour faire correspondre les tables aux classes java
     – Des beans Java simples correspondant aux objets métiers : ceux sont ces beans que manipule
       le développeur
     – Une API de persistance qui permet de rendre persistant dans la BD les beans métiers. On
       retrouve généralement les mêmes verbes (insert, update, delete, get)
     – Un langage de requêtes proche du SQL mais manipulant les propriétés des beans.



                                                                                                       6
Les besoins
• Clairement, 2 grands besoins se dégagèrent,
  répondant à l’industrie et aux développeurs:
1. Avoir une API simple d’utilisation, attrayante
   pour les développeurs, appliquant les
   techniques apprises des cadres d’applications
   de la communauté open source.
2. Avoir un standard respecté par les
   fournisseurs de serveurs d’applications.

                                                7
Motivations



•La couche [1], (User Interface) est la couche qui dialogue avec
l'utilisateur, via une interface graphique Swing, une interface console
ou une interface web. Elle a pour rôle de fournir des données
provenant de l'utilisateur à la couche [2] ou bien de présenter à
l'utilisateur des données fournies par la couche [2].




                                                                    8
Motivations




La couche [2], est la couche qui applique les règles dites
métier, i.e., la logique spécifique de l'application, sans se
préoccuper de savoir d'où viennent les données qu'on lui
donne, ni où vont les résultats qu'elle produit.




                                                                9
Motivations



• La couche [3], (Data Access Object) est la couche qui fournit à
la couche [2] des données pré-enregistrées (fichiers, bases de
données, ...) et qui enregistre certains des résultats fournis par la
couche [2].
• la couche *JDBC+ est la couche standard utilisée en Java pour
accéder à des bases de données. C'est ce qu'on appelle
habituellement le pilote Jdbc du SGBD




                                                                    10
Avec Hibernate

• La couche [Hibernate] vient se placer entre la couche [dao] écrite par le
  développeur et la couche [Jdbc]. Hibernate est un ORM (Object Relational
  Mapping), un outil qui fait le pont entre le monde relationnel des bases de
  données et celui des objets manipulés par Java. Le développeur de la
  couche [dao] ne voit plus la couche [Jdbc] ni les tables de la base de
  données dont il veut exploiter le contenu. Il ne voit que l'image objet de la
  base de données, image objet fournie par la couche [Hibernate].
• Le pont entre les tables de la base de données et les objets manipulés
  par la couche [dao] est faite principalement de deux façons :
   – par des fichiers de configuration de type XML
   – par des annotations Java dans le code, technique disponible
      seulement depuis le JDK 1.5

                                                                             11
Cependant…
• Hibernate est populaire mais complexe à maîtriser:
   – Dès qu'on a une base de données avec des tables ayant des relations
     un-à-plusieurs ou plusieurs-à-plusieurs, la configuration du pont
     relationnel / objets n'est pas évidente.
   – Des erreurs de configuration peuvent alors conduire à des applications
     peu performantes.
• La solution TopLink (commerciale)




                                                                         12
Finalement JPA
•  Sun standardise une couche ORM via une spécification appelée JPA
  (apparue avec Java 5).
• La couche [dao] dialogue maintenant avec la spécification JPA, un
  ensemble d'interfaces. Le développeur y a gagné en standardisation, i.e.,
  Avant, s'il changeait sa couche ORM, il devait également changer sa
  couche [dao] qui avait été écrite pour dialoguer avec un ORM spécifique.
  Maintenant, il va écrire une couche [dao] qui va dialoguer avec une
  couche JPA. Quelque soit le produit qui implémente celle-ci, l'interface de
  la couche JPA présentée à la couche [dao] reste la même.




                                                                            13
Présentation de JPA
• JPA est un standard pour la persistance des objets Java
    – L'API JPA est récente. Elle n'a été disponible qu'à partir du JDK 1.6.
    – L'API de persistance est accessible en utilisant le paquetage Java
      javax.persistence.
    – La spécification JPA a été implémentée par les deux produits : Toplink
      et Hibernate.
• L'API Java Persistence repose sur :
    – des entités qui sont de simples POJOs (Plain Old Java Object).
      annotés, et
    – un gestionnaire de ces entités (EntityManager) qui propose des
      fonctionnalités pour les manipuler (ajout, modification suppression,
      recherche). Ce gestionnaire est responsable de la gestion de l'état des
      entités et de leur persistance dans la base de données.




                                                                            14
Outils JPA
• Open source
  – Eclipse 3.2.x w
  – NetBeans 5.5
• Commerciaux
  – Oracle Jdeveloper
  – BEA Workshop Studio (Eclipse++)
  – JBoss IDE (Eclipse++) gratuit


                                      15
personne                                         matiere

                          + cin_pers    : int                               + code_mat : int
                          + nom_pers    : java.lang.String                  + nom_mat : java.lang.String
                          + prenom_pers : java.lang.String

                                                                                                  0..*
                                                                                           0..*

                                                                                                  filiere
                        prof                       Etudiant
                                                                     0..*           + code_fil : int
             + grade : java.lang.String       + moy_et : float                      + nom_fil : java.lang.String
                                                                            1..1




                                                                                                                     matiere

                                                                                                            code_mat int         <pk>
                                                                     personne                               nom_mat varchar(254)

                                                         cin_pers    int          <pk>
                                                         nom_pers    varchar(254)                                              FK_filMat

POJO:                                                    prenom_pers varchar(254)
                                                                                                                                             fil_mat
- Personne                                                                                                                        code_fil int <pk,fk1>
                                                                                                                                  code_mat int <pk,fk2>
- Prof                                                   FK_Heritage_1
                                                                               FK_Heritage_2
- Etudiant                                                                                                                                 FK_filMat
- Filiere                                                    prof                                Etudiant
- Matiere    Fichiers XML                     cin_pers int          <pk,fk>            cin_pers int <pk,fk2>       FK_etFil
                                                                                                                                           filiere

                                              grade    varchar(254)                    code_fil int <fk1>                      code_fil int         <pk>
                                                                                       moy_et float                            nom_fil varchar(254)

                                                                                                                                                       11
matiere

                                                                                   + code_mat : int
                                                                                   + nom_mat : java.lang.String



package persistClass;                      <?xml version="1.0"?>
                                           <!DOCTYPE hibernate-mapping PUBLIC
public class Matiere {                     "-//Hibernate/Hibernate Mapping DTD
private String nom;                        3.0//EN"
private Integer codeMat;                   "http://hibernate.sourceforge.net/hibernat
                                           e-mapping-3.0.dtd">     package
public Matiere(){}
public Matiere(Integer code,String nom)    <hibernate-mapping>
{                                          <class name="persistClass.Matiere"
          this.nom = nom;                  table="matiere">                 POJO
          this.codeMat=code;
}                                          <id name="codeMat" type="int"
                                                       column="code_mat"></id>
public String getNom() {                    Clé primaire
          return nom;
}                                          <property name="nom" type="string"
public void setNom(String nom) {
          this.nom = nom;                   attribut length="50" column="nom_mat"/>
}
public Integer getCodeMat() {              </class>
          return codeMat;                  </hibernate-mapping>
}
public void setCodeMat(Integer code) {    - Ce fichier xml sera sauvegardé sous le nom Matiere.hbm.xml
          this.codeMat = code;            et dans le même répertoire que son POJO correspondant.
}
}                                         - On peut aussi mapper tous les POJO dans un seul fichier.

                                                                                                           12
Comparaison Hibernate vs JPA
• Points Communs
   – Offrir des services de persistance
   – Mapping Objet/Relationnel déclaratif
   – Adopter un langage de requêtes
• Points de divergence
   – JPA est une brique de base du standard Java EE 5
   – Hibernate est un Framework alors que JPA est une spécification
     (API)
   – Hibernate peut être utilisé comme fournisseur de persistance
   – JPA utilise les annotations Java 5 pour assurer le mapping
   – JPA est plus simple à mettre en œuvre que Hibernate (Entity
     Manager, pas de fichiers de mapping, …)


                                                                  18
Mapping Objet Relationnel
La communication entre les mondes objet et relationnel suppose
une transformation pour adapter la structure des données
relationnelles au modèle objet.




                                                                 19
Fichier de configuration :
                 persistence.xml
• Un seul fichier de configuration XML
   – Il est nécessaire d’indiquer au fournisseur de persistance comment il
     peut se connecter à la base de données
   – Ce fichier peut aussi comporter d’autres informations
• Le fichier persistence.xml doit être stocké dans le répertoire
  META−INF
• La racine du document XML du fichier persistence.xml est le tag
  <persistence>.
• Il contient un ou plusieurs tags <persistence−unit> qui va contenir
  les paramètres d'un persistence unit. Ce tag possède deux attributs
   – : name (obligatoire) qui précise le nom de l'unité et qui servira à y faire
     référence et
   – transaction−type (optionnel) qui précise le type de transaction utilisée
     (ceci dépend de l'environnement d'exécution : Java SE ou Java EE).


                                                                              20
Fichier de configuration




                           21
Les Entités
• Les classes dont les instances peuvent être persistantes
  sont appelées des entités dans la spécification de JPA
   – Le développeur indique qu’une classe est une entité en lui
     associant l’annotation @Entity
   – Il faut importer javax.persistence.Entity dans les classes
     entités.
• Les entités dans les spécifications de l'API Java Persistence
  permettent d'encapsuler les données d'une occurrence
  d'une ou plusieurs tables.
• Ce sont de simples POJO
   – Un POJO est une classe Java qui n'implémente aucune interface
     particulière ni n'hérite d'aucune classe mère spécifique.



                                                                  22
Cycle de vie d’une entité




                            23
Classes entités : Entity Class
• Une classe entité doit posséder un attribut qui représente
  la clé primaire dans la BD (@Id)
   – Elle doit avoir un constructeur sans paramètre protected ou
     public sans argument et la classe du bean doit obligatoirement
     être marquée avec l'annotation @javax.persistence.Entity.
     Cette annotation possède un attribut optionnel nommé name
     qui permet de préciser le nom de l'entité dans les requêtes. Par
     défaut, ce nom est celui de la classe de l'entité.

   – Elle ne doit pas être final
   – Aucune méthode ou champ persistant ne doit être final
   – Une entité peut être une classe abstraite mais elle ne peut pas
     être une interface


                                                                    24
Les annotations
Annotation                          Rôle
@javax.persistence.Table            Préciser le nom de la table concernée par
                                    le mapping
@javax.persistence.Column           Associé à un getter, il permet d'associer
                                    un champ de la table à la propriété
@javax.persistence.Id               Associé à un getter, il permet d'associer
                                    un champ de la table à la propriété en
                                    tant que clé primaire
@javax.persistence.GeneratedValue   Demander la génération automatique de
                                    la clé primaire au besoin
@javax.persistence.Basic            Représenter la forme de mapping la plus
                                    simple. Cette annotation est utilisée par
                                    défaut
@javax.persistence.Transient        Demander de ne pas tenir compte du
                                    champ lors du mapping
                                                                                25
L'annotation
              @javax.persistence.Table
• Permet de lier l'entité à une table de la base
  de données. Par défaut, l'entité est liée à la
  table de la base de données correspondant au
  nom de la classe de l'entité. Si ce nom est
  différent alors l'utilisation de l'annotation
  @Table est obligatoire.
  Attributs            Rôle
  name                 Nom de la table
  catalog              Catalogue de la table
  …                    …
                                               26
L'annotation
              @javax.persistence.Column
•   Permet d'associer un membre de l'entité à une colonne de la table. Par défaut, les
    champs de l'entité sont liés aux champs de la table dont les noms correspondent.
    Si ces noms sont différents alors l'utilisation de l'annotation @Column est
    obligatoire.
     Attributs     Rôle
     name          Nom de la colonne
     table         Nom de la table dans le cas d'un mapping multi−table
     unique        Indique si la colonne est unique

     Nullable      Indique si la colonne est nullable
     insertable    Indique si la colonne doit être prise en compte dans les requêtes de
                   type insert
     updatable     Indique si la colonne doit être prise en compte dans les requêtes de
                   type update

                                                                                     27
L'annotation @Id
• Il faut obligatoirement définir une des propriétés de la
  classe avec l'annotation @Id pour la déclarer comme
  étant la clé primaire de la table.
• Cette annotation peut marquer soit le champ de la
  classe concernée soit le getter de la propriété.
• L'utilisation de l'un ou l'autre précise au gestionnaire
  s’il doit se baser sur les champs ou les getter pour
  déterminer les associations entre l'entité et les champs
  de la table. La clé primaire peut être constituée d'une
  seule propriété ou composées de plusieurs propriétés
  qui peuvent être de type primitif ou chaîne de
  caractères

                                                         28
EXEMPLE
import java.io.Serializable; import javax.persistence.Entity; import
    javax.persistence.GeneratedValue; import javax.persistence.Id;
@Entity
public class Personne implements Serializable {
@Id
@GeneratedValue
private int id;
private String prenom; private String nom;
private static final long serialVersionUID = 1L;
public Personne() { super(); }
public int getId() { return this.id; }
public void setId(int id) {this.id = id; }
public String getPrenom() { return this.prenom; }
public void setPrenom(String prenom) {this.prenom = prenom;}
public String getNom() {return this.nom; }
public void setNom(String nom) { this.nom = nom;}
}                                                                      29
Cas d’une Clé primaire composée
• Le modèle de base de données relationnelle
  permet la définition d'une clé primaire
  composée de plusieurs colonnes.
• L'API Java Persistence propose deux façons de
  gérer ce cas de figure :
  – L'annotation @javax.persistence.IdClass
  – L'annotation @javax.persistence.EmbeddedId



                                                 30
L'annotation @javax.persistence.IdClass



• L'annotation @IdClass s'utilise avec une classe
  qui va encapsuler les propriétés qui
  composent la clé primaire. Cette classe doit
  obligatoirement :
  – Être sérialisable
  – Posséder un constructeur sans arguments
  – Fournir une implémentation dédiée des méthodes
    equals() et hashCode()


                                                      31
Exemple: PersonnePK (1/3)
public class PersonnePK implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String nom; private String prenom;
public PersonnePK() { }
public PersonnePK(String nom, String prenom) {this.nom = nom; this.prenom = prenom; }
public String getNom() { return this.nom;}
public void setNom(String nom) { this.nom = nom; }
public String getPrenom() {return prenom;}
public void setPrenom(String prenom) {this.nom = prenom;}
public boolean equals(Object obj) { boolean resultat = false;
if (obj == this) {resultat = true;}
 else { if (!(obj instanceof PersonnePK)) { resultat = false;}
else { PersonnePK autre = (PersonnePK) obj;
if (!nom.equals(autre.nom)) {resultat = false;}
 else {if (prenom != autre.prenom) {resultat = false;}
 else { resultat = true; }} }}
return resultat;
}
public int hashCode() {return (nom + prenom).hashCode();}}
                                                                                        32
Exemple: (2/3)
• Il est nécessaire de définir la classe de la clé primaire dans le fichier de
  configuration persistence.xml

<?xml version="1.0" encoding="UTF−8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema−instance"
version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence−unit name="MaBaseDeTestPU">
<provider>oracle.toplink.essentials.PersistenceProvider</provider>
<class>com.jmd.test.jpa.Personne</class>
<class>com.jmd.test.jpa.PersonnePK</class>
</persistence−unit>
</persistence>


                                                                                 33
•
                             Exemple (3/3)
    Il faut utiliser l'annotation@IdClass sur la classe de l'entité.
•   Il est nécessaire de marquer chacune des propriétés de l'entité qui compose la clé primaire
    avec l'annotation @Id. Ces propriétés doivent avoir le même nom dans l'entité et dans la
    classe qui encapsule la clé primaire.
import java.io.Serializable; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.IdClass;
@Entity
@IdClass(PersonnePK.class)
public class Personne implements Serializable {
private String prenom; private String nom; private int taille;
private static final long serialVersionUID = 1L;
public Personne() { super();}
@Id
public String getPrenom() {return this.prenom;}
public void setPrenom(String prenom) {this.prenom = prenom;}
@Id
public String getNom() {return this.nom;}
public void setNom(String nom) {this.nom = nom;}
public int getTaille() {return this.taille;}
public void setTaille(int taille) {this.taille = taille;}}
                                                                                                  34
Classes entités : Embedded Class
• Il existe des classes incorporées (embedded)
  dont les données n’ont pas d’identité dans la
  BD mais sont insérées dans une des tables
  associées à une entité persistante
  – Par exemple, une classe Adresse dont les valeurs
    sont insérées dans la table Employe




                                                   35
EntityManager
• Classe javax.persistence.EntityManager
   – Le gestionnaire d’entités est l’interlocuteur principal pour le
     développeur.
• Les interactions entre la base de données et les beans
  entité sont assurées par un objet de type
  javax.persistence.EntityManager : il permet de lire et
  rechercher des données mais aussi de les mettre à jour
  (ajout, modification, suppression). L'EntityManager est
  donc au coeur de toutes les actions de persistance.
   – Il fournit les méthodes pour gérer les entités :
       •   les rendre persistantes,
       •   les supprimer de la base de données,
       •   retrouver leurs valeurs dans la base,
       •   etc.

                                                                       36
Cycle de vie d’un EntityManager
• La méthode createEntityManager() de la
  classe EntityManagerFactory créé un Entity
  Manager
  – L’Entity Manager est supprimé avec la méthode
    close() de la classe EntityManager, il ne sera plus
    possible de l’utiliser ensuite.




                                                      37
Fabrique de l’EntityManager
• La classe Persistence permet d’obtenir une
  fabrique de gestionnaire d’entités par la méthode
  createEntityManagerFactory
• 2 variantes surchargées de cette méthode :
  – 1 seul paramètre qui donne le nom de l’unité de
    persistance (définie dans le fichier persistence.xml)
  – Un 2ème paramètre de type Map qui contient des
    valeurs qui vont écraser les propriétés par défaut
    contenues dans persistence.xml

                                                            38
Méthodes de EntityManager
• void flush()
     • Toutes les modifications effectuées sur les entités du
       contexte de persistance gérées par l’EntityManager
       sont enregistrées dans la BD
  – void persist(Object entité)
     • Une entité nouvelle devient une entité gérée, l’état de
       l’entité sera sauvegardé dans la BD au prochain flush ou
       commit.
  – void remove(Object entité)
     • Une entité gérée devient supprimée, les données
       correspondantes seront supprimées de la BD

                                                                39
Méthodes de EntityManager
• void lock(Object entité, LockModeType lockMode)
   – Le fournisseur de persistance gère les accès concurrents aux
     données de la BD représentées par les entités avec une stratégie
     optimiste, lock permet de modifier la manière de gérer les accès
     concurrents à une entité
• void refresh(Object entité)
       • L’EntityManager peut synchroniser avec la BD une entité qu’il gère en
         rafraichissant son état en mémoire avec les données actuellement
         dans la BD.
       • Utiliser cette méthode pour s’assurer que l’entité a les mêmes
         données que la BD.
• <T> T find(Class<T> classeEntité,Object cléPrimaire)
       • La recherche est polymorphe : l'entité récupérée peut être de la classe
         passée en paramètre ou d'une sous-classe (renvoie null si aucune
         entité n’a l’identificateur passé en paramètre)


                                                                              40
Utilisation de EntityManager pour la
       création d'une occurrence
• Pour insérer une nouvelle entité dans la base
  de données, il faut :
  – Instancier une occurrence de la classe de l'entité
  – Initialiser les propriétés de l'entité
  – Définir les relations de l'entité avec d'autres
    entités, et au besoin
  – Utiliser la méthode persist() de l'EntityManager en
    passant en paramètre l'entité


                                                      41
EXEMPLE
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class TestJPA {
public static void main(String[]argv) {
EntityManagerFactory emf =
   Persistence.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
EntityTransaction transac = em.getTransaction();
transac.begin();
   Personne nouvellePersonne = new Personne();
   nouvellePersonne.setId(4);
   nouvellePersonne.setNom("nom4");
   nouvellePersonne.setPrenom("prenom4");
   em.persist(nouvellePersonne);
transac.commit();
em.close();
                                                             42
emf.close();}}
Utilisation de EntityManager pour
      rechercher des occurrences
• Pour effectuer des recherches de données,
  l'EntityManager propose deux mécanismes :
   – La recherche à partir de la clé primaire
   – La recherche à partir d'une requête utilisant une
     syntaxe dédiée
• Pour la recherche par clé primaire, la classe
  EntityManager possède les méthodes find()
  et getReference() qui attendent toutes les
  deux en paramètres un objet de type Class
  représentant la classe de l'entité et un objet qui
  contient la valeur de la clé primaire.

                                                         43
Avec Find()
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class TestJPA5 {
public static void main(String[] argv) {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
Personne personne = em.find(Personne.class, 4);
if (personne != null) {
System.out.println("Personne.nom=" + personne.getNom());
}
em.close();
emf.close();
}
}                                                          44
Avec getReference()
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityNotFoundException;
import javax.persistence.Persistence;
public class TestJPA6 {
public static void main(String[] argv) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
try {
Personne personne = em.getReference(Personne.class, 5);
System.out.println("Personne.nom=" + personne.getNom());
} catch (EntityNotFoundException e) { System.out.println("personne non trouvée"); }
em.close();
emf.close(); } }



                                                                                 45
Queries
• Il est possible de rechercher des données sur des
  critères plus complexes que la simple identité.
  Les étapes sont alors les suivantes :
  1.   Décrire ce qui est recherché (langage JPQL)
  2.   Créer une instance de type Query
  3.   Initialiser la requête (paramètres, pagination)
  4.   Lancer l’exécution de la requête
• JPA introduit le JPQL (Java Persistence Query
  Language), qui est, tout comme le EJBQL ou
  encore le HQL, un langage de requête du modèle
  objet, basé sur SQL.

                                                         46
Interface Query
• Représente une requête
  – Une instance de Query (d’une classe
    implémentant Query) est obtenue des méthodes
    dédiées de la classe EntityManager :
    • createQuery (),
    • createNativeQuery () ou
    • createNamedQuery ()




                                               47
L'objet Query
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class TestJPA7 {
public static void main(String[] argv) {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("select p from Personne p where p.nom='nom2'");
Personne personne = (Personne) query.getSingleResult();
if (personne == null) {
System.out.println("Personne non trouvée");
} else { System.out.println("Personne.nom=" + personne.getNom());
}
em.close(); emf.close();
}
}
                                                                               48
Query+la méthode getResultList()
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class TestJPA8 {
public static void main(String[] argv) {
EntityManagerFactory emf =
    Persistence.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("select p.nom from Personne p where p.id > 2");
List noms = query.getResultList();
for (Object nom : noms) { System.out.println("nom = "+nom); }
em.close();
emf.close();
}
                                                                               49
}
Les paramètres nommés+
import java.util.List;
                       setParameter()
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class TestJPA9 {
public static void main(String[] argv) {
EntityManagerFactory emf =
     Persistence.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("select p.nom from Personne p where p.id > :id");
query.setParameter("id", 1);
List noms = query.getResultList();
for (Object nom : noms) { System.out.println("nom = "+nom); }
em.close();
emf.close();
                                                                                 50
}}
modifier une occurrence avec le
            EntityManager
• Pour modifier une entité existante dans la
  base de données, il faut :
  – Obtenir une instance de l'entité à modifier (par
    recherche sur la clé primaire ou l'exécution d'une
    requête)
  – Modifier les propriétés de l'entité
  – Selon le mode de synchronisation des données de
    l'EntityManager, il peut être nécessaire d'appeler
    la méthode flush() explicitement

                                                     51
Exemple
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class TestJPA10 { public static void main(String[] argv) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
EntityTransaction transac = em.getTransaction();
transac.begin();
Query query = em.createQuery("select p from Personne p where p.nom='nom2'");
Personne personne = (Personne) query.getSingleResult();
if (personne == null) { System.out.println("Personne non trouvée");}
 else { System.out.println("Personne.prenom=" + personne.getPrenom());
personne.setPrenom("prenom2 modifié");
em.flush();
personne = (Personne) query.getSingleResult();
System.out.println("Personne.prenom=" + personne.getPrenom());
} transac.commit();
                                                                                       52
supprimer une occurrence avec
           EntityManager
• Pour supprimer une entité existante dans la
  base de données:
  – Obtenir une instance de l'entité à supprimer (par
    recherche sur la clé primaire ou l'exécution d'une
    requête)
  – Appeler la méthode remove() de l'EntityManager
    en lui passant en paramètre l'instance de l'entité



                                                         53
Exemple
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class TestJPA12 { public static void main(String[] argv) {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
EntityTransaction transac = em.getTransaction();
transac.begin();
Personne personne = em.find(Personne.class, 4);
if (personne == null) { System.out.println("Personne non trouvée");
} else { em.remove(personne);
}
transac.commit(); em.close(); emf.close(); } }

                                                                      54
Rafraîchir les données d'une
                     occurrence
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class TestJPA13 { public static void main(String[] argv) {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("MaBaseDeTestPU");
EntityManager em = emf.createEntityManager();
EntityTransaction transac = em.getTransaction();
transac.begin();
Personne personne = em.find(Personne.class, 4);
if (personne == null) { System.out.println("Personne non trouvée");
} else { em.refresh(personne);
}
transac.commit(); em.close(); emf.close();
}
}
                                                                      55
Queries: NamedQueries
• Peut être mise dans n’importe quelle entité,
  mais on choisira le plus souvent l’entité qui
  correspond à ce qui est renvoyé par la
  requête
• On peut sauvegarder des gabarits de requête
  dans nos entités. Ceci permet :
  – La réutilisation de la requête
  – D’externaliser les requête du code.

                                              56
@Entity
@NamedQuery(name="myQuery", query="Select o from MyPojo
   o")
public class MyPojo { … }
public class MyService {
public void myMethod() {…
List results =
em.createNamedQuery("myQuery").getResultList();…




                                                      57
Queries: NativeQueries
• Une façon de faire des requête en SQL natif.
   – Sert principalement à avoir plus de contrôle sur les requêtes à la base
     de donnée
public class MyService {
public void myMethod() {
…
List results
= em.createNativeQuery(“SELECT * FROM MyPojo“, MyPojo.class)
.getResultList();
…
}
}



                                                                           58
Relations
• Dans le modèle des bases de données relationnelles,
  les tables peuvent être liées entre elles grâce à des
  relations.
• Ces relations sont transposées dans les liaisons que
  peuvent les différentes entités correspondantes.
• 4 types de relations à définir entre les entités de la
  JPA:
   –   1−1 (One to One)
   –   1−n (Many to One)
   –   1−n (One to Many)
   –   n−n (Many to Many)

                                                           59
Relationships: One to One




                            60
Relationship: Many to One




                            61
Relationship: One to Many




                            62
Relationships: Many to Many




                              63

Contenu connexe

Tendances

Tendances (20)

Hibernate
HibernateHibernate
Hibernate
 
Introduction à Hibernate p.1
Introduction à Hibernate p.1Introduction à Hibernate p.1
Introduction à Hibernate p.1
 
4 Hibernate
4 Hibernate4 Hibernate
4 Hibernate
 
Springioc
SpringiocSpringioc
Springioc
 
Hibernate
HibernateHibernate
Hibernate
 
Hibernate 3
Hibernate 3Hibernate 3
Hibernate 3
 
JNDI Java Naming Derectory Interfaces
JNDI Java Naming Derectory InterfacesJNDI Java Naming Derectory Interfaces
JNDI Java Naming Derectory Interfaces
 
La persistance des données : ORM et hibernate
La persistance des données : ORM et hibernateLa persistance des données : ORM et hibernate
La persistance des données : ORM et hibernate
 
Hibernate vs le_cloud_computing
Hibernate vs le_cloud_computingHibernate vs le_cloud_computing
Hibernate vs le_cloud_computing
 
575
575575
575
 
Cours JavaScript
Cours JavaScriptCours JavaScript
Cours JavaScript
 
Devoxx 15
Devoxx 15 Devoxx 15
Devoxx 15
 
Hibernate et jsf
Hibernate et jsfHibernate et jsf
Hibernate et jsf
 
Introduction a Java
Introduction a JavaIntroduction a Java
Introduction a Java
 
Formation JAVA/J2EE
Formation JAVA/J2EEFormation JAVA/J2EE
Formation JAVA/J2EE
 
Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014
 
Tutoriel java
Tutoriel javaTutoriel java
Tutoriel java
 
Ce bon vieux propel
Ce bon vieux propelCe bon vieux propel
Ce bon vieux propel
 
CDI mis en pratique avec Seam Social et Weld OSGI
CDI mis en pratique avec Seam Social et Weld OSGICDI mis en pratique avec Seam Social et Weld OSGI
CDI mis en pratique avec Seam Social et Weld OSGI
 
Et pourquoi pas JEE ?
Et pourquoi pas JEE ?Et pourquoi pas JEE ?
Et pourquoi pas JEE ?
 

En vedette

Von wegen schwergewichtig - Moderne Webentwicklung mit Java EE 7
Von wegen schwergewichtig - Moderne Webentwicklung mit Java EE 7Von wegen schwergewichtig - Moderne Webentwicklung mit Java EE 7
Von wegen schwergewichtig - Moderne Webentwicklung mit Java EE 7
Stefan Macke
 
20091020 JPA2
20091020 JPA220091020 JPA2
20091020 JPA2
lyonjug
 
ខ្លឹមសារគួរយល់ដឹង
ខ្លឹមសារគួរយល់ដឹងខ្លឹមសារគួរយល់ដឹង
ខ្លឹមសារគួរយល់ដឹង
Vantha Kago
 

En vedette (20)

Von wegen schwergewichtig - Moderne Webentwicklung mit Java EE 7
Von wegen schwergewichtig - Moderne Webentwicklung mit Java EE 7Von wegen schwergewichtig - Moderne Webentwicklung mit Java EE 7
Von wegen schwergewichtig - Moderne Webentwicklung mit Java EE 7
 
Architectures 3-tiers (Web)
Architectures 3-tiers (Web)Architectures 3-tiers (Web)
Architectures 3-tiers (Web)
 
20091020 JPA2
20091020 JPA220091020 JPA2
20091020 JPA2
 
Effiziente datenpersistierung mit JPA 2.1 und Hibernate
Effiziente datenpersistierung mit JPA 2.1 und HibernateEffiziente datenpersistierung mit JPA 2.1 und Hibernate
Effiziente datenpersistierung mit JPA 2.1 und Hibernate
 
Zehn Jahre JPA – Architekturkonzepte und Best Practices revisited
Zehn Jahre JPA – Architekturkonzepte und Best Practices revisitedZehn Jahre JPA – Architekturkonzepte und Best Practices revisited
Zehn Jahre JPA – Architekturkonzepte und Best Practices revisited
 
Java EE Pattern: The Control Layer
Java EE Pattern: The Control LayerJava EE Pattern: The Control Layer
Java EE Pattern: The Control Layer
 
Designing JEE Application Structure
Designing JEE Application StructureDesigning JEE Application Structure
Designing JEE Application Structure
 
Java EE Pattern: Entity Control Boundary Pattern and Java EE
Java EE Pattern: Entity Control Boundary Pattern and Java EEJava EE Pattern: Entity Control Boundary Pattern and Java EE
Java EE Pattern: Entity Control Boundary Pattern and Java EE
 
Java EE Pattern: The Boundary Layer
Java EE Pattern: The Boundary LayerJava EE Pattern: The Boundary Layer
Java EE Pattern: The Boundary Layer
 
Top 50 java ee 7 best practices [con5669]
Top 50 java ee 7 best practices [con5669]Top 50 java ee 7 best practices [con5669]
Top 50 java ee 7 best practices [con5669]
 
50 EJB 3 Best Practices in 50 Minutes - JavaOne 2014
50 EJB 3 Best Practices in 50 Minutes - JavaOne 201450 EJB 3 Best Practices in 50 Minutes - JavaOne 2014
50 EJB 3 Best Practices in 50 Minutes - JavaOne 2014
 
Overview of JPA (Java Persistence API) v2.0
Overview of JPA (Java Persistence API) v2.0Overview of JPA (Java Persistence API) v2.0
Overview of JPA (Java Persistence API) v2.0
 
Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)Entreprise Java Beans (EJB)
Entreprise Java Beans (EJB)
 
Application de gestion des projets en J2EE (Spring-Hibernate) avec architectu...
Application de gestion des projets en J2EE (Spring-Hibernate) avec architectu...Application de gestion des projets en J2EE (Spring-Hibernate) avec architectu...
Application de gestion des projets en J2EE (Spring-Hibernate) avec architectu...
 
Maven et industrialisation du logiciel
Maven et industrialisation du logicielMaven et industrialisation du logiciel
Maven et industrialisation du logiciel
 
ខ្លឹមសារគួរយល់ដឹង
ខ្លឹមសារគួរយល់ដឹងខ្លឹមសារគួរយល់ដឹង
ខ្លឹមសារគួរយល់ដឹង
 
Conseil d’administration ou de connections? Saidatou Dicko
Conseil d’administration ou de connections? Saidatou DickoConseil d’administration ou de connections? Saidatou Dicko
Conseil d’administration ou de connections? Saidatou Dicko
 
BACHELOR
BACHELORBACHELOR
BACHELOR
 
33700
3370033700
33700
 
Kompetent Prüfen am PC Workshop 2010
Kompetent Prüfen am PC Workshop 2010Kompetent Prüfen am PC Workshop 2010
Kompetent Prüfen am PC Workshop 2010
 

Similaire à Jpa(1)

Cours java smi_2011_2012_partie_i_29_octobre_2011
Cours java smi_2011_2012_partie_i_29_octobre_2011Cours java smi_2011_2012_partie_i_29_octobre_2011
Cours java smi_2011_2012_partie_i_29_octobre_2011
yassine kchiri
 
Java Code to Java Heap - En Français
Java Code to Java Heap - En FrançaisJava Code to Java Heap - En Français
Java Code to Java Heap - En Français
Chris Bailey
 
Langage Java et Programmation Orienté Objet
Langage Java et Programmation Orienté ObjetLangage Java et Programmation Orienté Objet
Langage Java et Programmation Orienté Objet
Mohammed Jaafar
 
Mappingobjetrelationnel[1]
Mappingobjetrelationnel[1]Mappingobjetrelationnel[1]
Mappingobjetrelationnel[1]
linasafaa
 
Ado.net vs jpa
Ado.net vs jpaAdo.net vs jpa
Ado.net vs jpa
Netways
 

Similaire à Jpa(1) (20)

POO Licence L2 Partie I.pdf
POO Licence L2 Partie I.pdfPOO Licence L2 Partie I.pdf
POO Licence L2 Partie I.pdf
 
4711538.pptx
4711538.pptx4711538.pptx
4711538.pptx
 
Seance_1_cours_introduction_java_Copie.pptx
Seance_1_cours_introduction_java_Copie.pptxSeance_1_cours_introduction_java_Copie.pptx
Seance_1_cours_introduction_java_Copie.pptx
 
JPA est middleware
JPA est middleware JPA est middleware
JPA est middleware
 
Cours java smi_2011_2012_partie_i_29_octobre_2011
Cours java smi_2011_2012_partie_i_29_octobre_2011Cours java smi_2011_2012_partie_i_29_octobre_2011
Cours java smi_2011_2012_partie_i_29_octobre_2011
 
Hibernate
HibernateHibernate
Hibernate
 
Javavs net
Javavs netJavavs net
Javavs net
 
Java Code to Java Heap - En Français
Java Code to Java Heap - En FrançaisJava Code to Java Heap - En Français
Java Code to Java Heap - En Français
 
Ejb3 2-session-beans fr
Ejb3 2-session-beans frEjb3 2-session-beans fr
Ejb3 2-session-beans fr
 
OOP and Design Patterns
OOP and Design PatternsOOP and Design Patterns
OOP and Design Patterns
 
OOP & Design Pattern - Algiers Developers Meetup August 2015
OOP & Design Pattern - Algiers Developers Meetup August 2015OOP & Design Pattern - Algiers Developers Meetup August 2015
OOP & Design Pattern - Algiers Developers Meetup August 2015
 
POO-Cours.pdf
POO-Cours.pdfPOO-Cours.pdf
POO-Cours.pdf
 
CDI par la pratique
CDI par la pratiqueCDI par la pratique
CDI par la pratique
 
Framework Hibernate
Framework HibernateFramework Hibernate
Framework Hibernate
 
Langage Java et Programmation Orienté Objet
Langage Java et Programmation Orienté ObjetLangage Java et Programmation Orienté Objet
Langage Java et Programmation Orienté Objet
 
Programmation Java
Programmation JavaProgrammation Java
Programmation Java
 
Mappingobjetrelationnel[1]
Mappingobjetrelationnel[1]Mappingobjetrelationnel[1]
Mappingobjetrelationnel[1]
 
Crs orm
Crs ormCrs orm
Crs orm
 
Chapitre 1 introduction generale
Chapitre 1   introduction generaleChapitre 1   introduction generale
Chapitre 1 introduction generale
 
Ado.net vs jpa
Ado.net vs jpaAdo.net vs jpa
Ado.net vs jpa
 

Jpa(1)

  • 1. La solution de persistance en Java: JPA Sadok Ben Yahia
  • 2. Motivation L’Objet est devenu le style fondamental de la programmation UML Conception O2, EyeBD Comment faire correspondance entre O/R Base de données OO Développement ??? Langage orienté objet: java c# c++... 4
  • 3. Solution ? ORM : Object / Relational Mapping encapsulation attribut SQL ligne 5
  • 4. ORM c’est quoi? Le mapping objet relationnel crée une illusion d’une BDOO à partir d’une BDR Donc on peut bénéficier de l’orienté objet et gérer une BD relationnelle d’une façon transparente. public class Obj { private int id; private String name; Id name public Obj(){ } .. .. public Obj(String name) { … .. this.name = name; … .. } public void setId(int i) { id = i; } …. } Il existe plusieurs Framework de mapping objet/relationnel : Java Persistance API, TopLink, Java Data Object, Hibernate, Object Relational Bridge… 7
  • 5. Un peu d’histoire … • Entity Beans EJB 1.0 -> 2.1 – Complexité • EJB2.x "entity" et les EJB2.x "session » : – un EJB2.x "entity" est l'image d'une ligne de table de BD – EJB2.x "session" un objet utilisé pour implémenter les couches [metier], [dao] d'une architecture multi-couches • La courbe d’apprentissage trop prononcée • Modèle de programmation non-intuitif (ne sont utilisables qu'au sein de conteneurs EJB) – Performance • Le coût pour effectuer certaines requêtes était hors de proportions, 5
  • 6. Un peu d’histoire … • Les équipes IT se sont de plus en plus tournés vers d’autres produits sur le marché: • Hibernate – Le plus répandu dans la communauté présentement. Toutefois, la responsabilité de compatibilité avec différents serveurs d’application revient à la communauté. • JDO – Bien que JDO soit un standard, appuyé par la JSR 243 (JDO 2.0), cette technologie a reçu bien peu d’appui. • Produits commerciaux (ex. TopLink) – API propriétaires, onéreux, non-standard … • Ces trois solutions fonctionnent globalement suivant les mêmes principes : – Des fichiers de mapping pour faire correspondre les tables aux classes java – Des beans Java simples correspondant aux objets métiers : ceux sont ces beans que manipule le développeur – Une API de persistance qui permet de rendre persistant dans la BD les beans métiers. On retrouve généralement les mêmes verbes (insert, update, delete, get) – Un langage de requêtes proche du SQL mais manipulant les propriétés des beans. 6
  • 7. Les besoins • Clairement, 2 grands besoins se dégagèrent, répondant à l’industrie et aux développeurs: 1. Avoir une API simple d’utilisation, attrayante pour les développeurs, appliquant les techniques apprises des cadres d’applications de la communauté open source. 2. Avoir un standard respecté par les fournisseurs de serveurs d’applications. 7
  • 8. Motivations •La couche [1], (User Interface) est la couche qui dialogue avec l'utilisateur, via une interface graphique Swing, une interface console ou une interface web. Elle a pour rôle de fournir des données provenant de l'utilisateur à la couche [2] ou bien de présenter à l'utilisateur des données fournies par la couche [2]. 8
  • 9. Motivations La couche [2], est la couche qui applique les règles dites métier, i.e., la logique spécifique de l'application, sans se préoccuper de savoir d'où viennent les données qu'on lui donne, ni où vont les résultats qu'elle produit. 9
  • 10. Motivations • La couche [3], (Data Access Object) est la couche qui fournit à la couche [2] des données pré-enregistrées (fichiers, bases de données, ...) et qui enregistre certains des résultats fournis par la couche [2]. • la couche *JDBC+ est la couche standard utilisée en Java pour accéder à des bases de données. C'est ce qu'on appelle habituellement le pilote Jdbc du SGBD 10
  • 11. Avec Hibernate • La couche [Hibernate] vient se placer entre la couche [dao] écrite par le développeur et la couche [Jdbc]. Hibernate est un ORM (Object Relational Mapping), un outil qui fait le pont entre le monde relationnel des bases de données et celui des objets manipulés par Java. Le développeur de la couche [dao] ne voit plus la couche [Jdbc] ni les tables de la base de données dont il veut exploiter le contenu. Il ne voit que l'image objet de la base de données, image objet fournie par la couche [Hibernate]. • Le pont entre les tables de la base de données et les objets manipulés par la couche [dao] est faite principalement de deux façons : – par des fichiers de configuration de type XML – par des annotations Java dans le code, technique disponible seulement depuis le JDK 1.5 11
  • 12. Cependant… • Hibernate est populaire mais complexe à maîtriser: – Dès qu'on a une base de données avec des tables ayant des relations un-à-plusieurs ou plusieurs-à-plusieurs, la configuration du pont relationnel / objets n'est pas évidente. – Des erreurs de configuration peuvent alors conduire à des applications peu performantes. • La solution TopLink (commerciale) 12
  • 13. Finalement JPA • Sun standardise une couche ORM via une spécification appelée JPA (apparue avec Java 5). • La couche [dao] dialogue maintenant avec la spécification JPA, un ensemble d'interfaces. Le développeur y a gagné en standardisation, i.e., Avant, s'il changeait sa couche ORM, il devait également changer sa couche [dao] qui avait été écrite pour dialoguer avec un ORM spécifique. Maintenant, il va écrire une couche [dao] qui va dialoguer avec une couche JPA. Quelque soit le produit qui implémente celle-ci, l'interface de la couche JPA présentée à la couche [dao] reste la même. 13
  • 14. Présentation de JPA • JPA est un standard pour la persistance des objets Java – L'API JPA est récente. Elle n'a été disponible qu'à partir du JDK 1.6. – L'API de persistance est accessible en utilisant le paquetage Java javax.persistence. – La spécification JPA a été implémentée par les deux produits : Toplink et Hibernate. • L'API Java Persistence repose sur : – des entités qui sont de simples POJOs (Plain Old Java Object). annotés, et – un gestionnaire de ces entités (EntityManager) qui propose des fonctionnalités pour les manipuler (ajout, modification suppression, recherche). Ce gestionnaire est responsable de la gestion de l'état des entités et de leur persistance dans la base de données. 14
  • 15. Outils JPA • Open source – Eclipse 3.2.x w – NetBeans 5.5 • Commerciaux – Oracle Jdeveloper – BEA Workshop Studio (Eclipse++) – JBoss IDE (Eclipse++) gratuit 15
  • 16. personne matiere + cin_pers : int + code_mat : int + nom_pers : java.lang.String + nom_mat : java.lang.String + prenom_pers : java.lang.String 0..* 0..* filiere prof Etudiant 0..* + code_fil : int + grade : java.lang.String + moy_et : float + nom_fil : java.lang.String 1..1 matiere code_mat int <pk> personne nom_mat varchar(254) cin_pers int <pk> nom_pers varchar(254) FK_filMat POJO: prenom_pers varchar(254) fil_mat - Personne code_fil int <pk,fk1> code_mat int <pk,fk2> - Prof FK_Heritage_1 FK_Heritage_2 - Etudiant FK_filMat - Filiere prof Etudiant - Matiere Fichiers XML cin_pers int <pk,fk> cin_pers int <pk,fk2> FK_etFil filiere grade varchar(254) code_fil int <fk1> code_fil int <pk> moy_et float nom_fil varchar(254) 11
  • 17. matiere + code_mat : int + nom_mat : java.lang.String package persistClass; <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC public class Matiere { "-//Hibernate/Hibernate Mapping DTD private String nom; 3.0//EN" private Integer codeMat; "http://hibernate.sourceforge.net/hibernat e-mapping-3.0.dtd"> package public Matiere(){} public Matiere(Integer code,String nom) <hibernate-mapping> { <class name="persistClass.Matiere" this.nom = nom; table="matiere"> POJO this.codeMat=code; } <id name="codeMat" type="int" column="code_mat"></id> public String getNom() { Clé primaire return nom; } <property name="nom" type="string" public void setNom(String nom) { this.nom = nom; attribut length="50" column="nom_mat"/> } public Integer getCodeMat() { </class> return codeMat; </hibernate-mapping> } public void setCodeMat(Integer code) { - Ce fichier xml sera sauvegardé sous le nom Matiere.hbm.xml this.codeMat = code; et dans le même répertoire que son POJO correspondant. } } - On peut aussi mapper tous les POJO dans un seul fichier. 12
  • 18. Comparaison Hibernate vs JPA • Points Communs – Offrir des services de persistance – Mapping Objet/Relationnel déclaratif – Adopter un langage de requêtes • Points de divergence – JPA est une brique de base du standard Java EE 5 – Hibernate est un Framework alors que JPA est une spécification (API) – Hibernate peut être utilisé comme fournisseur de persistance – JPA utilise les annotations Java 5 pour assurer le mapping – JPA est plus simple à mettre en œuvre que Hibernate (Entity Manager, pas de fichiers de mapping, …) 18
  • 19. Mapping Objet Relationnel La communication entre les mondes objet et relationnel suppose une transformation pour adapter la structure des données relationnelles au modèle objet. 19
  • 20. Fichier de configuration : persistence.xml • Un seul fichier de configuration XML – Il est nécessaire d’indiquer au fournisseur de persistance comment il peut se connecter à la base de données – Ce fichier peut aussi comporter d’autres informations • Le fichier persistence.xml doit être stocké dans le répertoire META−INF • La racine du document XML du fichier persistence.xml est le tag <persistence>. • Il contient un ou plusieurs tags <persistence−unit> qui va contenir les paramètres d'un persistence unit. Ce tag possède deux attributs – : name (obligatoire) qui précise le nom de l'unité et qui servira à y faire référence et – transaction−type (optionnel) qui précise le type de transaction utilisée (ceci dépend de l'environnement d'exécution : Java SE ou Java EE). 20
  • 22. Les Entités • Les classes dont les instances peuvent être persistantes sont appelées des entités dans la spécification de JPA – Le développeur indique qu’une classe est une entité en lui associant l’annotation @Entity – Il faut importer javax.persistence.Entity dans les classes entités. • Les entités dans les spécifications de l'API Java Persistence permettent d'encapsuler les données d'une occurrence d'une ou plusieurs tables. • Ce sont de simples POJO – Un POJO est une classe Java qui n'implémente aucune interface particulière ni n'hérite d'aucune classe mère spécifique. 22
  • 23. Cycle de vie d’une entité 23
  • 24. Classes entités : Entity Class • Une classe entité doit posséder un attribut qui représente la clé primaire dans la BD (@Id) – Elle doit avoir un constructeur sans paramètre protected ou public sans argument et la classe du bean doit obligatoirement être marquée avec l'annotation @javax.persistence.Entity. Cette annotation possède un attribut optionnel nommé name qui permet de préciser le nom de l'entité dans les requêtes. Par défaut, ce nom est celui de la classe de l'entité. – Elle ne doit pas être final – Aucune méthode ou champ persistant ne doit être final – Une entité peut être une classe abstraite mais elle ne peut pas être une interface 24
  • 25. Les annotations Annotation Rôle @javax.persistence.Table Préciser le nom de la table concernée par le mapping @javax.persistence.Column Associé à un getter, il permet d'associer un champ de la table à la propriété @javax.persistence.Id Associé à un getter, il permet d'associer un champ de la table à la propriété en tant que clé primaire @javax.persistence.GeneratedValue Demander la génération automatique de la clé primaire au besoin @javax.persistence.Basic Représenter la forme de mapping la plus simple. Cette annotation est utilisée par défaut @javax.persistence.Transient Demander de ne pas tenir compte du champ lors du mapping 25
  • 26. L'annotation @javax.persistence.Table • Permet de lier l'entité à une table de la base de données. Par défaut, l'entité est liée à la table de la base de données correspondant au nom de la classe de l'entité. Si ce nom est différent alors l'utilisation de l'annotation @Table est obligatoire. Attributs Rôle name Nom de la table catalog Catalogue de la table … … 26
  • 27. L'annotation @javax.persistence.Column • Permet d'associer un membre de l'entité à une colonne de la table. Par défaut, les champs de l'entité sont liés aux champs de la table dont les noms correspondent. Si ces noms sont différents alors l'utilisation de l'annotation @Column est obligatoire. Attributs Rôle name Nom de la colonne table Nom de la table dans le cas d'un mapping multi−table unique Indique si la colonne est unique Nullable Indique si la colonne est nullable insertable Indique si la colonne doit être prise en compte dans les requêtes de type insert updatable Indique si la colonne doit être prise en compte dans les requêtes de type update 27
  • 28. L'annotation @Id • Il faut obligatoirement définir une des propriétés de la classe avec l'annotation @Id pour la déclarer comme étant la clé primaire de la table. • Cette annotation peut marquer soit le champ de la classe concernée soit le getter de la propriété. • L'utilisation de l'un ou l'autre précise au gestionnaire s’il doit se baser sur les champs ou les getter pour déterminer les associations entre l'entité et les champs de la table. La clé primaire peut être constituée d'une seule propriété ou composées de plusieurs propriétés qui peuvent être de type primitif ou chaîne de caractères 28
  • 29. EXEMPLE import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Personne implements Serializable { @Id @GeneratedValue private int id; private String prenom; private String nom; private static final long serialVersionUID = 1L; public Personne() { super(); } public int getId() { return this.id; } public void setId(int id) {this.id = id; } public String getPrenom() { return this.prenom; } public void setPrenom(String prenom) {this.prenom = prenom;} public String getNom() {return this.nom; } public void setNom(String nom) { this.nom = nom;} } 29
  • 30. Cas d’une Clé primaire composée • Le modèle de base de données relationnelle permet la définition d'une clé primaire composée de plusieurs colonnes. • L'API Java Persistence propose deux façons de gérer ce cas de figure : – L'annotation @javax.persistence.IdClass – L'annotation @javax.persistence.EmbeddedId 30
  • 31. L'annotation @javax.persistence.IdClass • L'annotation @IdClass s'utilise avec une classe qui va encapsuler les propriétés qui composent la clé primaire. Cette classe doit obligatoirement : – Être sérialisable – Posséder un constructeur sans arguments – Fournir une implémentation dédiée des méthodes equals() et hashCode() 31
  • 32. Exemple: PersonnePK (1/3) public class PersonnePK implements java.io.Serializable { private static final long serialVersionUID = 1L; private String nom; private String prenom; public PersonnePK() { } public PersonnePK(String nom, String prenom) {this.nom = nom; this.prenom = prenom; } public String getNom() { return this.nom;} public void setNom(String nom) { this.nom = nom; } public String getPrenom() {return prenom;} public void setPrenom(String prenom) {this.nom = prenom;} public boolean equals(Object obj) { boolean resultat = false; if (obj == this) {resultat = true;} else { if (!(obj instanceof PersonnePK)) { resultat = false;} else { PersonnePK autre = (PersonnePK) obj; if (!nom.equals(autre.nom)) {resultat = false;} else {if (prenom != autre.prenom) {resultat = false;} else { resultat = true; }} }} return resultat; } public int hashCode() {return (nom + prenom).hashCode();}} 32
  • 33. Exemple: (2/3) • Il est nécessaire de définir la classe de la clé primaire dans le fichier de configuration persistence.xml <?xml version="1.0" encoding="UTF−8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema−instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence−unit name="MaBaseDeTestPU"> <provider>oracle.toplink.essentials.PersistenceProvider</provider> <class>com.jmd.test.jpa.Personne</class> <class>com.jmd.test.jpa.PersonnePK</class> </persistence−unit> </persistence> 33
  • 34. Exemple (3/3) Il faut utiliser l'annotation@IdClass sur la classe de l'entité. • Il est nécessaire de marquer chacune des propriétés de l'entité qui compose la clé primaire avec l'annotation @Id. Ces propriétés doivent avoir le même nom dans l'entité et dans la classe qui encapsule la clé primaire. import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; @Entity @IdClass(PersonnePK.class) public class Personne implements Serializable { private String prenom; private String nom; private int taille; private static final long serialVersionUID = 1L; public Personne() { super();} @Id public String getPrenom() {return this.prenom;} public void setPrenom(String prenom) {this.prenom = prenom;} @Id public String getNom() {return this.nom;} public void setNom(String nom) {this.nom = nom;} public int getTaille() {return this.taille;} public void setTaille(int taille) {this.taille = taille;}} 34
  • 35. Classes entités : Embedded Class • Il existe des classes incorporées (embedded) dont les données n’ont pas d’identité dans la BD mais sont insérées dans une des tables associées à une entité persistante – Par exemple, une classe Adresse dont les valeurs sont insérées dans la table Employe 35
  • 36. EntityManager • Classe javax.persistence.EntityManager – Le gestionnaire d’entités est l’interlocuteur principal pour le développeur. • Les interactions entre la base de données et les beans entité sont assurées par un objet de type javax.persistence.EntityManager : il permet de lire et rechercher des données mais aussi de les mettre à jour (ajout, modification, suppression). L'EntityManager est donc au coeur de toutes les actions de persistance. – Il fournit les méthodes pour gérer les entités : • les rendre persistantes, • les supprimer de la base de données, • retrouver leurs valeurs dans la base, • etc. 36
  • 37. Cycle de vie d’un EntityManager • La méthode createEntityManager() de la classe EntityManagerFactory créé un Entity Manager – L’Entity Manager est supprimé avec la méthode close() de la classe EntityManager, il ne sera plus possible de l’utiliser ensuite. 37
  • 38. Fabrique de l’EntityManager • La classe Persistence permet d’obtenir une fabrique de gestionnaire d’entités par la méthode createEntityManagerFactory • 2 variantes surchargées de cette méthode : – 1 seul paramètre qui donne le nom de l’unité de persistance (définie dans le fichier persistence.xml) – Un 2ème paramètre de type Map qui contient des valeurs qui vont écraser les propriétés par défaut contenues dans persistence.xml 38
  • 39. Méthodes de EntityManager • void flush() • Toutes les modifications effectuées sur les entités du contexte de persistance gérées par l’EntityManager sont enregistrées dans la BD – void persist(Object entité) • Une entité nouvelle devient une entité gérée, l’état de l’entité sera sauvegardé dans la BD au prochain flush ou commit. – void remove(Object entité) • Une entité gérée devient supprimée, les données correspondantes seront supprimées de la BD 39
  • 40. Méthodes de EntityManager • void lock(Object entité, LockModeType lockMode) – Le fournisseur de persistance gère les accès concurrents aux données de la BD représentées par les entités avec une stratégie optimiste, lock permet de modifier la manière de gérer les accès concurrents à une entité • void refresh(Object entité) • L’EntityManager peut synchroniser avec la BD une entité qu’il gère en rafraichissant son état en mémoire avec les données actuellement dans la BD. • Utiliser cette méthode pour s’assurer que l’entité a les mêmes données que la BD. • <T> T find(Class<T> classeEntité,Object cléPrimaire) • La recherche est polymorphe : l'entité récupérée peut être de la classe passée en paramètre ou d'une sous-classe (renvoie null si aucune entité n’a l’identificateur passé en paramètre) 40
  • 41. Utilisation de EntityManager pour la création d'une occurrence • Pour insérer une nouvelle entité dans la base de données, il faut : – Instancier une occurrence de la classe de l'entité – Initialiser les propriétés de l'entité – Définir les relations de l'entité avec d'autres entités, et au besoin – Utiliser la méthode persist() de l'EntityManager en passant en paramètre l'entité 41
  • 42. EXEMPLE import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class TestJPA { public static void main(String[]argv) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); EntityTransaction transac = em.getTransaction(); transac.begin(); Personne nouvellePersonne = new Personne(); nouvellePersonne.setId(4); nouvellePersonne.setNom("nom4"); nouvellePersonne.setPrenom("prenom4"); em.persist(nouvellePersonne); transac.commit(); em.close(); 42 emf.close();}}
  • 43. Utilisation de EntityManager pour rechercher des occurrences • Pour effectuer des recherches de données, l'EntityManager propose deux mécanismes : – La recherche à partir de la clé primaire – La recherche à partir d'une requête utilisant une syntaxe dédiée • Pour la recherche par clé primaire, la classe EntityManager possède les méthodes find() et getReference() qui attendent toutes les deux en paramètres un objet de type Class représentant la classe de l'entité et un objet qui contient la valeur de la clé primaire. 43
  • 44. Avec Find() import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class TestJPA5 { public static void main(String[] argv) { EntityManagerFactory emf = Persistence .createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); Personne personne = em.find(Personne.class, 4); if (personne != null) { System.out.println("Personne.nom=" + personne.getNom()); } em.close(); emf.close(); } } 44
  • 45. Avec getReference() import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityNotFoundException; import javax.persistence.Persistence; public class TestJPA6 { public static void main(String[] argv) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); try { Personne personne = em.getReference(Personne.class, 5); System.out.println("Personne.nom=" + personne.getNom()); } catch (EntityNotFoundException e) { System.out.println("personne non trouvée"); } em.close(); emf.close(); } } 45
  • 46. Queries • Il est possible de rechercher des données sur des critères plus complexes que la simple identité. Les étapes sont alors les suivantes : 1. Décrire ce qui est recherché (langage JPQL) 2. Créer une instance de type Query 3. Initialiser la requête (paramètres, pagination) 4. Lancer l’exécution de la requête • JPA introduit le JPQL (Java Persistence Query Language), qui est, tout comme le EJBQL ou encore le HQL, un langage de requête du modèle objet, basé sur SQL. 46
  • 47. Interface Query • Représente une requête – Une instance de Query (d’une classe implémentant Query) est obtenue des méthodes dédiées de la classe EntityManager : • createQuery (), • createNativeQuery () ou • createNamedQuery () 47
  • 48. L'objet Query import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; public class TestJPA7 { public static void main(String[] argv) { EntityManagerFactory emf = Persistence .createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); Query query = em.createQuery("select p from Personne p where p.nom='nom2'"); Personne personne = (Personne) query.getSingleResult(); if (personne == null) { System.out.println("Personne non trouvée"); } else { System.out.println("Personne.nom=" + personne.getNom()); } em.close(); emf.close(); } } 48
  • 49. Query+la méthode getResultList() import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; public class TestJPA8 { public static void main(String[] argv) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); Query query = em.createQuery("select p.nom from Personne p where p.id > 2"); List noms = query.getResultList(); for (Object nom : noms) { System.out.println("nom = "+nom); } em.close(); emf.close(); } 49 }
  • 50. Les paramètres nommés+ import java.util.List; setParameter() import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; public class TestJPA9 { public static void main(String[] argv) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); Query query = em.createQuery("select p.nom from Personne p where p.id > :id"); query.setParameter("id", 1); List noms = query.getResultList(); for (Object nom : noms) { System.out.println("nom = "+nom); } em.close(); emf.close(); 50 }}
  • 51. modifier une occurrence avec le EntityManager • Pour modifier une entité existante dans la base de données, il faut : – Obtenir une instance de l'entité à modifier (par recherche sur la clé primaire ou l'exécution d'une requête) – Modifier les propriétés de l'entité – Selon le mode de synchronisation des données de l'EntityManager, il peut être nécessaire d'appeler la méthode flush() explicitement 51
  • 52. Exemple import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import javax.persistence.Query; public class TestJPA10 { public static void main(String[] argv) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); EntityTransaction transac = em.getTransaction(); transac.begin(); Query query = em.createQuery("select p from Personne p where p.nom='nom2'"); Personne personne = (Personne) query.getSingleResult(); if (personne == null) { System.out.println("Personne non trouvée");} else { System.out.println("Personne.prenom=" + personne.getPrenom()); personne.setPrenom("prenom2 modifié"); em.flush(); personne = (Personne) query.getSingleResult(); System.out.println("Personne.prenom=" + personne.getPrenom()); } transac.commit(); 52
  • 53. supprimer une occurrence avec EntityManager • Pour supprimer une entité existante dans la base de données: – Obtenir une instance de l'entité à supprimer (par recherche sur la clé primaire ou l'exécution d'une requête) – Appeler la méthode remove() de l'EntityManager en lui passant en paramètre l'instance de l'entité 53
  • 54. Exemple import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class TestJPA12 { public static void main(String[] argv) { EntityManagerFactory emf = Persistence .createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); EntityTransaction transac = em.getTransaction(); transac.begin(); Personne personne = em.find(Personne.class, 4); if (personne == null) { System.out.println("Personne non trouvée"); } else { em.remove(personne); } transac.commit(); em.close(); emf.close(); } } 54
  • 55. Rafraîchir les données d'une occurrence import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class TestJPA13 { public static void main(String[] argv) { EntityManagerFactory emf = Persistence .createEntityManagerFactory("MaBaseDeTestPU"); EntityManager em = emf.createEntityManager(); EntityTransaction transac = em.getTransaction(); transac.begin(); Personne personne = em.find(Personne.class, 4); if (personne == null) { System.out.println("Personne non trouvée"); } else { em.refresh(personne); } transac.commit(); em.close(); emf.close(); } } 55
  • 56. Queries: NamedQueries • Peut être mise dans n’importe quelle entité, mais on choisira le plus souvent l’entité qui correspond à ce qui est renvoyé par la requête • On peut sauvegarder des gabarits de requête dans nos entités. Ceci permet : – La réutilisation de la requête – D’externaliser les requête du code. 56
  • 57. @Entity @NamedQuery(name="myQuery", query="Select o from MyPojo o") public class MyPojo { … } public class MyService { public void myMethod() {… List results = em.createNamedQuery("myQuery").getResultList();… 57
  • 58. Queries: NativeQueries • Une façon de faire des requête en SQL natif. – Sert principalement à avoir plus de contrôle sur les requêtes à la base de donnée public class MyService { public void myMethod() { … List results = em.createNativeQuery(“SELECT * FROM MyPojo“, MyPojo.class) .getResultList(); … } } 58
  • 59. Relations • Dans le modèle des bases de données relationnelles, les tables peuvent être liées entre elles grâce à des relations. • Ces relations sont transposées dans les liaisons que peuvent les différentes entités correspondantes. • 4 types de relations à définir entre les entités de la JPA: – 1−1 (One to One) – 1−n (Many to One) – 1−n (One to Many) – n−n (Many to Many) 59