Post on 15-Jul-2015
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 1/176
4.1: Couche Persistance EJB3/JPA
Formation Java EE 5 / Spring
Par Adel ELJ, Architecte J2EE
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 2/176
Esprit 2009/ 2010
Page 2
Adel ELJ (Architecte J2EE)
EJB 3.0
E x e m p
l e
r é f é
r e n c e
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 3/176
Esprit 2009/ 2010
Page 3
Adel ELJ (Architecte J2EE)
I.Présentation de JPA
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 4/176
Esprit 2009/ 2010
Page 4
Adel ELJ (Architecte J2EE)
• Java EE 5 (Enterprise Edition) est uneplateforme de développement et un ensemblede spécifications pour le développementd’applications d’entreprises multi-tiers
• EJB 3 fait partie de Java EE 5 ; c’est unespécification récente (mai 2006) d’un cadre(framework) pour l’utilisation de composantsmétier réutilisables par des serveursd’applications Java
EJB 3.0
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 5/176Esprit 2009/ 2010
Page 5
Adel ELJ (Architecte J2EE)
• JPA (Java persistence API) est la partie de laspécification EJB 3.0 qui concerne lapersistance des composants dans une base dedonnées Relationnelle
• Peut s’appliquer sur toutes les applicationsJava, même celles qui s’exécutent en dehorsd’un serveur d’applications
JPA
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 6/176Esprit 2009/ 2010
Page 6
Adel ELJ (Architecte J2EE)
• Transparente : les classes des entitéspersistantes sont indifférentes au mécanismede persistance
• Automatique : des appels simples de hautniveau pour gérer la persistance, tels quepersist(objet) pour rendre un objet persistant ;pas d’appel de bas niveau comme avec JDBC
Solution ORM
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 7/176Esprit 2009/ 2010
Page 7
Adel ELJ (Architecte J2EE)
• Comme pour JDBC, l’utilisation de JPA nécessiteun fournisseur de persistance qui implémenteles classes et méthodes de l’API
• GlassFish, est l’implémentation de référence dela spécification EJB 3
• GlassFish utilise TopLink essentials commefournisseur de persistance pour JPA (produitOracle)
• D’autres implémentations : TopLink, HibernateEntity Manager, BEA Kodo
Fournisseur de persistance
P 8
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 8/176Esprit 2009/ 2010
Page 8
Adel ELJ (Architecte J2EE)
• Les classes dont les instances peuvent êtrepersistantes sont appelées des entités dans laspécification de JPA
• Le développeur indique qu’une classe est uneentité en lui associant l’annotation @Entity
• Ne pas oublier d’importer javax.Persistence.Entity dans les classesentités (idem pour toutes les annotations)
Entités
Page 9
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 9/176Esprit 2009/ 2010
Page 9
Adel ELJ (Architecte J2EE)
Exemple d’entité – les champs
Page 10
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 10/176Esprit 2009/ 2010
Page 10
Adel ELJ (Architecte J2EE)
/**
* Constructeur sans paramètre
* obligatoire.*/
public Departement() { }
public Departement(String nom, String lieu) {this.nom = nom;
this.lieu = lieu;
}
Les constructeurs
Page 11
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 11/176Esprit 2009/ 2010
Page 11
Adel ELJ (Architecte J2EE)
@Id
@GeneratedValue public int getId() {
return id;
} public void setId(int id) {
this.id = id;
}
Exemple d’entité – l’identificateur
Page 12
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 12/176Esprit 2009/ 2010
Page 12
Adel ELJ (Architecte J2EE)
public String getNom() {return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
Exemple d’entité – une propriété
Page 13
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 13/176Esprit 2009/ 2010
Page 13
Adel ELJ (Architecte J2EE)
@OneToMany (mappedBy="dept")
public Collection<Employe> getEmployes() {
return employes;
}
public void setEmployes(Collection<Employe> emps) {this.employes = emps;
}
Exemple d’entité – une association
Page 14
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 14/176Esprit 2009/ 2010
g
Adel ELJ (Architecte J2EE)
• Il est nécessaire d’indiquer aufournisseur de persistance comment il
peut se connecter à la base de données• Les informations doivent être donnéesdans un fichier p er s ist en ce.x m l situé
dans un répertoire META- I NF dans leclasspath
• Ce fichier peut aussi comporter d’autresinformations ; il est étudié en détailsdans la suite du cours
Configuration de la connexion
Page 15
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 15/176
Esprit 2009/ 2010
g
Adel ELJ (Architecte J2EE)
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="Employes">
<class>jpa.Departement</class>
<class>jpa.Employe</class>
<properties><property name="toplink.jdbc.driver"
value="oracle.jdbc.OracleDriver"/>
<property name="toplink.jdbc.url"
value="jdbc:oracle:thin:@cl.truc.fr:1521:XE"/>
Exemple (début)
Page 16
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 16/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
<property name="toplink.jdbc.user“
value="toto"/>
<property name="toplink.jdbc.password“
value="xxxxx"/>
</properties>
</persistence-unit>
</persistence>
Exemple (fin)
Page 17
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 17/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Classe javax.persistence.EntityManager
• Le gestionnaire d’entités (GE) est l’interlocuteurprincipal pour le développeur
• Il fournit les méthodes pour gérer les entités : lesrendre persistantes, les supprimer de la base de
données, retrouver leurs valeurs dans la base, etc.
Gestionnaire d’entités
Page 18
Exemple de code (1)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 18/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("employes");
EntityManager em = emf.createEntityManager();EntityTransaction tx = em.getTransaction();
em.tx.begin();Dept dept = new Dept("Direction", "Nice");
em.persist(dept);
dept.setLieu("Paris");
tx.commit();
Exemple de code (1)en dehors d’un serveur d’application
Page 19
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 19/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
String queryString = "SELECT e FROM Employe e " +
“WHERE e.poste = :poste";
Query query = em.createQuery(queryString);query.setParameter("poste", "INGENIEUR");
List<Employe> liste = query.getResultList();
for (Employe e : liste) {
System.out.println(e.getNom());
}
em.close();
emf.close()
Exemple de code (2)
Page 20
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 20/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• La méthode persist(o b j e t ) de la classeEntityManager rend persistant un objet
• L’objet est ajouté à un contexte de persistance quiest géré par le GE
• Toute modification apportée à un objet du contextede persistance sera enregistrée dans la base dedonnées
• L’ensemble des entités gérées par un GE s’appelle
un contexte de persistance
Contexte de persistance
Page 21
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 21/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
II. Entités
Page 22
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 22/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Seules les entités peuvent être
o renvoyées par une requête (Query)o passées en paramètre d’une méthode d’un
EntityManager ou d’un Query
o le but d’une associationo référencées dans une requête JPQL
• Une classe entité peut utiliser d’autres classes pourconserver des états persistants (MappedSuperclassou Embedded étudiées plus loin)
Caractéristiques
Page 23
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 23/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Elle doit posséder un attribut qui représente la cléprimaire dans la BD (@Id)
• Une classe entité doit avoir un constructeur sansparamètre protected ou public
• Elle ne doit pas être final
• Aucune méthode ou champ persistant ne doit êtrefinal
• Si une instance peut être passée par valeur enparamètre d’une méthode comme un objetdétaché, elle doit implémenter Serializable
Conditions pour les classes entités
Page 24
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 24/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Le fournisseur de persistance accédera à la valeurd’une variable d’instanceo soit en accédant directement à la variable d’instanceo soit en passant par ses accesseurs (getter ou setter)
• Le type d’accès est déterminé par l’emplacementdes annotations (associées aux variables d’instanceou aux getter)
2 types d’accès
Page 25
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 25/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Les accesseurs (setter et getter) doivent êtreprotected ou public
• Ils peuvent contenir d’autres instructions que leseul code lié à la valeur de la variable sous-jacente
• Ces instructions seront exécutées par lefournisseur de persistance
• Si une exception est levée par un accesseur, latransaction est invalidée ; les exceptionscontrôlées sont enveloppées par unePersistenceException (non contrôlée, sousRuntimeException)
Accès par propriété
Page 26
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 26/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Le choix doit être le même pour toutes les classesd’une hiérarchie d’héritage (interdit de mélanger
les 2 façons)
• En programmation objet il est conseillé d’utiliser
plutôt les accesseurs que les accès directs auxchamps (meilleur contrôle des valeurs) ; c’est aussile cas avec JPA
• Rappel : le choix est déterminé par l'emplacementdes annotations ; elles sont associées soit auxaccesseurs, soit aux variables d'instance ; ne pas
mélanger les 2 !
Choix du type d’accès
Page 27
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 27/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• L’instance peut être
o nouvelle (new) : elle est créée mais pasassociée à un contexte de persistance
o gérée (managed) par un gestionnaire depersistance elle a une identité dans la base dedonnées (un objet peut devenir géré par laméthode persist, ou merge d’une entitédétachée ; un objet géré peut aussi provenird’une requête faite par un gestionnaire d’entitésou d’une navigation à partir d’un objet géré)
Cycle de vie d’une instance d’entité
Page 28
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 28/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
o détachée (detached) : elle a une identité dans labase mais elle n’est plus associée à un contextede persistance (une entité peut, par exemple,devenir détachée si le contexte de persistanceest vidé ou si elle est envoyée dans une autre
JVM par RMI)
o supprimée (removed): elle a une identité dans
la base ; elle est associée à un contexte depersistance et ce contexte doit la supprimer dela base de données (passe dans cet état par la
méthode remove)
Cycle de vie d’une instance d’entité
Page 29
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 29/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Cycle de vie d’une instance d’entité
find
query
Page 30
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 30/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Dans les cas simples, une table correspond à uneclasseo le nom de la table est le nom de la classeo les noms des colonnes correspondent aux noms
des attributs persistants
• Par exemple, les données de la classeDepartement sont enregistrées dans la tableDepartement (ou DEPARTEMENT) dont lescolonnes se nomment id, nom, lieu
Les tables de la base de données
Page 31
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 31/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• La configuration des classes entités suppose desvaleurs par défaut
• Il n’est nécessaire d’ajouter des informations deconfiguration que si ces valeurs par défaut neconviennent pas
• Par exemple, @Entity suppose que la table quicontient les données des instances de la classe a lemême nom que la classe
Configuration « par exception »
Page 32
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 32/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Pour donner à la table un autre nom que le nom dela classe, il faut ajouter une annotation @Table
• Exemple :@Entity
@Table(name="AUTRENOM")
public class Classe {
...}
Nom de Table
Page 33
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 33/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Pour donner à une colonne de la table un autrenom que le nom de l’attribut correspondant, il faut
ajouter une annotation @Column
• Cette annotation peut aussi comporter desattributs pour définir plus précisément la colonne
• Exemple :@Column(name="AUTRENOM",
Updatable=false, length=80)
public String getTruc() { ... }
Nom de Colonne
Page 34
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 34/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Les entités persistantes ne sont pas les seules classespersistantes
• Il existe aussi des classes « insérées » ou « incorporées »(embedded) dont les données n’ont pas d’identité dans la BDmais sont insérées dans une des tables associées à une entité
persistante
• Elles peuvent être annotées comme les entités (avec@Column par exemple)
• Par exemple, une classe Adresse dont les valeurs sontinsérées dans la table Employe
Classe Embeddable
Page 35
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 35/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Comme les entités, ces classes doivent avoir unconstructeur sans paramètre
• Les types permis pour leurs attributs sont lesmêmes que les types permis pour les attributs desentités
Classe Embeddable
Page 36
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 36/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@Embeddable
public class Adresse {
private int numero; private String rue;
private String ville;
. . .}
@Entity
public class Employe {@Embedded private Adresse adresse;
. . .
@Embeddable
public class Adresse {
private int numero;
private String rue;
private String ville;
. . .
}
@Entity
public class Employe {
@Embedded private Adresse adresse;
. . .
Classe Embeddable
Page 37
é é
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 37/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Une annotation spéciale n’est pas nécessaire si unattribut est de type énumération si l’énumération
est sauvegardée dans la BD sous la forme desnuméros des constantes de l’énumération de n)
• Si on souhaite sauvegarder les constantes sous la
forme de la forme d’une String qui représente lenom de la valeur de l’énumération, il faut utiliserl’annotation @En u m er at ed
• Exemple:@Enumerated (EnumType.STRING)
private TypeEmploye typeEmploye;
Annotation pour énumération
Page 38
l
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 38/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Lorsqu'une classe entité a un attribut de type temporel(Calendar ou Date de java.util), il est obligatoire
d'indiquer de quel type temporel est cet attribut par uneannotation @Tem p or al
• Cette indication permettra au fournisseur de persistancede savoir comment déclarer la colonne correspondantedans la base de données : une date (un jour), un tempssur 24 heures (heures, minutes, secondes à la
milliseconde près) ou un timeStamp (date + heure à lamicroseconde près)
Types temporels
Page 39
l l
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 39/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
3 types temporels dans l’énumération Tem po r a lTyp e :
o TemporalType.DATE : une date seule sans heure associéeo TemporalType.TIME : une heure
o TemporalType.TIMESTAMP : une date avec heure
• Correspondent aux 3 types de SQL ou du paquetage java.sql:Date, Time et Timestamp
• Exemple:@Temporal(TemporalType.DATE )
private Calendar dateEmbauche;
Annotation pour les types temporels
Page 40
T bl lti l
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 40/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Il est possible de sauvegarder une entité surplusieurs tables
• Voir @SecondaryTable dans la spécification JPA
C’est surtout utile pour les cas où la base dedonnées existe déjà et ne correspond pas tout à faitau modèle objet
Tables multiples
Page 41
S hé l ti l
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 41/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Dans le cas où le schéma relationnel est construitautomatiquement à partir des annotations, il est
possible de préciser des informations sur les tablesgénérées ou les colonnes de ces tables
• Par exemple, une contrainte d'unicité, ou "notnull", la longueur des colonnes de type varchar, laprécision des nombres à virgule, ou même le texte
entier qui permet de définir une colonne
Voir la spécification JPA pour plus de détails
Schéma relationnel
Page 42
E l
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 42/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Exemple
Entity
@Table(name="PARTICIPATION2",
uniqueConstraints =
@UniqueConstraint(
columnNames = {"EMPLOYE_ID", "PROJET_ID"})
)
public class Participation {...
}
Entity
@Table(name="PARTICIPATION2",
uniqueConstraints =
@UniqueConstraint(
columnNames =
{"EMPLOYE_ID", "PROJET_ID"})
)
public class Participation {...
}
Page 43
Types persistants
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 43/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Les champs des entités peuvent être d’à peu prèsn’importe quel type :
• Types primitifs• Types String, BigInteger, BigDecimal, classes
Enveloppes (Wrapper) des type primitifs (exemp:Integer), Date (des paquetages util et sql),Calendar, Time, Timestamp, et plus généralementSerializable
• Enumérations• Entités et collections d’entités, classes
«Embeddable »
Types persistants
Page 44
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 44/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
III. Gestionnaire d’entités
(Entity Manager) GE
Page 45
Principe de Base
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 45/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• La persistance des entités n’est pas transparente
• Une instance d’entité ne devient persistante quelorsque l’application appelle la méthode appropriéedu gestionnaire d’entité persist ou merge)
• Cette conception a été voulue par les concepteursde l’API par souci de flexibilité et pour permettreun contrôle fin sur la persistance des entités
Principe de Base
Page 46
Unité de persistance
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 46/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• C’est une configuration nommée qui
contient les informations nécessaires àl’utilisation d’une base de données
• Elle est associée à un ensemble declasses entités
Unité de persistance
Page 47
Configuration d’une unitéde persistance
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 47/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Les informations sur une unité de persistance sontdonnées dans un fichier persistence.xml situé
dans un sousrépertoire META-INF d’un desrépertoires du répertoire META d’un classpath
Voir section « Configuration d’une unité depersistance » dans la suite du cours
de persistance
Page 48
Contexte de persistance (1)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 48/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Les entités gérées par un gestionnaire d’entitésforment un contexte de persistance
• Quand une entité est incluse dans un contexte depersistance (persist ou merge), l’état de l’entité
est automatiquement sauvegardé dans la base aumoment du commit de la transaction
• Propriété importante : dans un contexte depersistance il n’existe pas 2 entités différentes quireprésentent des données identiques dans la base
Contexte de persistance (1)
Page 49
Contexte de persistance (2)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 49/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Un contexte de persistance ne peut appartenir qu’àune seule unité de persistance
• Une unité de persistance peut contenir plusieurscontextes de persistance
• C’est la responsabilité de l’application de s’assurerqu’une entité n’appartient qu’à un seul contexte depersistance (afin que 2 entités de 2 contextes depersistance différents ne puissent correspondre àdes données identiques dans la base de données)
Contexte de persistance (2)
Page 50
Contexte de persistance - cache
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 50/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Le contexte de persistance joue le rôle de cache etévite ainsi des accès à la base Performance
• Si le code veut récupérer des données (par un findou un query) qui correspondent à une entité du
contexte, ce sont les données du cache qui sontrenvoyées
• Important : si les données de la base ont étémodifiées (et validées) en parallèle dans la base(par exemple en dehors de l’application), lesdonnées récupérées ne tiennent pas compte de ces
modifications
Contexte de persistance cache
Page 51
Contexte de persistance - cache
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 51/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Ce fonctionnement peut être bénéfique :o meilleures performances,o isolation « lecture répétable » sans modifier les
paramètres de la base de données
• Mais si modifications effectuées en parallèle sur lesdonnées d’une entité
il est possible de les récupérer en utilisant laméthode re f resh de la classe EntityManager
Contexte de persistance cache
Page 52
Interface EntityManager
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 52/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Elle représente un GE
• L’implémentation de l’interface fournie par lefournisseur de persistance
Interface EntityManager
Page 53
Types de GE
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 53/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Types de GE
• GE géré par le container (uniquement disponibledans un serveur d’applications) ; le contexte de
persistance peut être limité à une seule transaction(cas d’un SLSB) ou à plusieurs (cas d’un SFSB)
• GE géré par l’application (type disponible endehors d’un serveur d’applications) ; le contexte depersistance reste attaché au GE pendant toute son
existence.
Page 54
Cycle de vie d’un GE
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 54/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• En dehors d’un serveur d’applications, c’estl’application qui décide de la durée de vie d’un GE
• La méthode createEntityManager() de la classeEntityManagerFactory créé un GE
• Le GE est supprimé avec la méthode close() de laclasse EntityManager ; il ne sera plus possible del’utiliser ensuite
Cycle de vie d un GE
Page 55
Fabrique de GE
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 55/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• La classe Pers is tence permet d’obtenir une fabrique degestionnaire d’entités par la méthodecrea teEn t i t yManagerFac to ry
• 2 variantes surchargées de cette méthode :
o 1 seul paramètre qui donne le nom de l’unité depersistance (définie dans le fichier persistence.xml)
o Un 2ème paramètre de type Map qui contient des valeursqui vont écraser les propriétés par défaut contenues danspersistence.xml
Fabrique de GE
Page 56
A savoir
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 56/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Une EntityManagerFactory est «threadsafe»
• Un EntityManager ne l’est pas
• Créer une EntityManagerFactory est une
opération lourde
• Créer un EntityManager est une opération légère
• Il est donc intéressant de conserver uneEntityManagerFactory entre 2 utilisations
A savoir
Page 57
Mauvaise configuration
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 57/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Si elle rencontre une mauvaise configuration(dans le fichier persistence.xml, dans lesannotations, y compris dans la syntaxe desrequêtes nommées ou dans les fichiers XML),la méthodePersistence.createEntityManagerFactoryne se terminera pas correctement et lanceraune exception
g
Page 58
Méthodes de EntityManager
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 58/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• void pers is t (Object e n t i t é )
• <T> T m er g e (T e n t i t é )
• void r em ov e (Object e n t i t é )
• <T> T f i n d (Class<T> c lasseEnt i té , Object cléPr im a i r e )
• <T> T ge tRe fe rence (Class<T> c lasseEnt i té , ObjectcléPr im a i r e )
• void f l ush ()
• void se tF lushMode (FlushModeType f l ushMode )
y g
Page 59
Méthodes de EntityManager
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 59/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• void lock (Object e n t i t é , LockModeType l ockMode )
• void r e f resh (Object e n t i t é )
• void clear ()
• boolean co n ta i n s (Object e n t i t é )
• Query crea teQuery (String r e q u ê t e )
• Query creat eNam edQuer y (String n om )
y g
Page 60
Méthodes de EntityManager
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 60/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Query crea teNat i veQuery (String r e q u ê t e )
• Query crea teNat i veQuery (String r e q u ê t e , Classc lasseRésul ta t )
• void jo inTransact ion ()
• void close ()
• boolean isOpen ()
• EntityTransaction ge tTransac t ion ()
y g
Page 61
flush
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 61/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Toutes les modifications effectuées sur les entitésdu contexte de persistance gérées par le GE sont
enregistrées dans la BD lors d’un f l ush du GE
• Au moment du f l ush , le GE étudie ce qu’il doit
faire pour chacune des entités qu’il gère et il lanceles commandes SQL adaptées pour modifier labase de données (INSERT, UPDATE ou DELETE)
Page 62
flush
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 62/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Un flush est automatiquement effectué au moins àchaque commit de la transaction en cours
• Une exception TransactionRequiredExceptionest levée si la méthode flush est lancée en dehors
d’une transaction
Page 63
Flush(à vérifier)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 63/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Soit X une des entités gérée, avec une associationde X vers une entité Y
• Si cette association est notée aveccascade=persist ou cascade=all, Y est aussiflushée
• Sinon, si Y est new ou removed, une exceptionIllegalStateException sera levée et la transactionest invalidée (rollback) (à tester)
• Sinon, si Y est détachée et X possède l’association,Y est flushée ; si Y est la propriétaire, lecomportement est indéfini
Page 64
Mode de flush
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 64/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Normalement (mode FlushMode.AUTO) un flush des entitésconcernées par une requête est effectué avant la requêtepour que le résultat tienne compte des modifications
effectuées en mémoire sur ces entités
• Il est possible d'éviter ce flush avec la méthode
setFlushMode : em.setFlushMode(FlushMode.COMMIT);
• En ce cas, un flush ne sera lancé qu'avant un commit
• Il est possible de modifier ce mode pour une seule requête(voir Query)
Page 65
persist
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 65/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Une entité « nouvelle » devient une entité gérée
• L’état de l’entité sera sauvegardé dans la BD auprochain flush ou commit
• Aucune instruction ne sera nécessaire pour faireenregistrer au moment du commit dans la base dedonnées les modifications effectuées sur l’entité
par l’application ; en effet le GE conserve toutesles informations nécessaires sur les entités qu’ilgère
Page 66
persist(A) A:une Entité
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 66/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Si A est nouvelle, elle devient gérée
• Si A était déjà gérée, persist est ignorée maisl’opération persist « cascade » sur les entitésassociées si l’association a l’attributCascadeType.PERSIST
• Si A est supprimée (a été passée en paramètre àremove), elle devient gérée
• Si A est détachée, uneIllegalArgumentException est lancée
Page 67
Remove(A)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 67/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Si A est gérée, elle devient « sup pr im ée » (lesdonnées correspondantes de la base seront
supprimées de la base au moment du flush ducontexte de persistance)
• I gn or ée si A est nouvelle ou supprimée
• Si A est détachée, uneIllegalArgumentException est lancée
• Ne peut être utilisé que dans le contexte d’unetransaction
Page 68
refresh
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 68/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Le GE peut synchroniser avec la BD une entité qu’ilgère en rafraichissant son état en mémoire avec
les données actuellement dans la BD :em.refresh(e n t i t e );
• Les données de la BD seront copiées dans l’entité
• Utiliser cette méthode pour s’assurer que l’entité ales mêmes données que la BD
• Peut être utile pour les contextes de persistence delongue durée
Page 69
refresh(A)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 69/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Ignorée si A est nouvelle ou supprimée
• Si A est nouvelle, l’opération « cascade » sur lesassociations qui ont l’attributCascadeType.REFRESH
• Si A est détachée, uneIllegalArgumentException est lancée
Page 70
find
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 70/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• La recherche est polymorphe : l'entité récupéréepeut ê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)
• Exemple :
Article p = em.find (Article.class, 128);
peut renvoyer un article de n'importe quelle sous-classe de Article (Stylo, Ramette,…)
Page 71
lock
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 71/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Le fournisseur de persistance gère les accèsconcurrents aux données de la BD représentées
par les entités avec une stratégie optimiste(optimistic locking)
• lock permet de modifier la manière de gérer lesaccès concurrents à une entité A
• Sera étudié plus loin dans la section sur laconcurrence
Page 72
Entité détachée (1)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 72/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Une application distribuée sur plusieurs ordinateurspeut utiliser avec profit des entités détachées
• Une entité gérée par un GE peut être détachée deson contexte de persistance ; par exemple, si le GE
est fermé ou si l’entité est transférée sur une autremachine en dehors de la portée du GE
Page 73
Entité détachée (2)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 73/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Une entité détachée peut être modifiée
• Pour que ces modifications soient enregistréesdans la BD, il est nécessaire de rattacher l’entité àun GE (pas nécessairement celui d’où elle a été
détachée) par la méthode m er g e
Page 74
merge(A)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 74/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Renvoie une entité gérée A’ ; plusieurs cas :
• Si A est une entité détachée, son état est copié dans uneentité gérée A’ qui a la même identité que A (si A’ n’existepas déjà, il est créé)
• Si A est nouvelle une nouvelle entité gérée A‘ est créé etl’état de A est copié dans A’ (un id automatique ne sera misdans A’ qu’au commit)
• Si A est déjà gérée, merge renvoie A ; en plus merge «cascade » pour tous les associations avec l’attributCascadeType.MERGE
Page 75
merge(A)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 75/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Si A a été marquée « supprimée » par la méthoderemove, une IllegalArgumentException est
lancée
Page 76
merge(A)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 76/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Attention, la méthode merge n’attache pas A
• Elle retourne une entité gérée qui a la même identité dans laBD que l’entité passée en paramètre, mais ça n’est pas lemême objet ( sauf si A était déjà gérée)
• Après un merge, l’application devra donc, sauf casexceptionnel, ne plus utiliser l’objet A ; on pourra avoir cetype de code :
a = em.merge(a);
l’objet anciennement pointé par a ne sera plusréférencé
Page 77
En dehors d’une transaction (1)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 77/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Les méthodes suivantes (read only) peuvent êtrelancées en dehors d’une transaction : find,getReference, refresh et requêtes (query)
• Les méthodes persist, remove, merge peuventêtre exécutées en dehors d’une transaction ; lesmodifications qu’elles ont provoquées serontenregistrées par un flush dès qu’une transactionest active
• Les méthodes flush, lock et modifications demasse (executeUpdate) ne peuvent être lancéesen dehors d’une transaction
Page 78
En dehors d’une transaction (2)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 78/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• En fait, certains SGBD se mettent en modeautocommit lorsque des modifications sont
effectuées sur des entités gérées en dehors d’unetransaction, ce qui peut poser de sérieuxproblèmes (en cas de rollback de la transaction par
l’application, ces modifications ne seront pasinvalidées)
Il est donc conseillé de n’effectuer les modificationssur les entités gérées que dans le contexte d’unetransaction, ou au moins de tester lecomportement du SGBD
Page 79
Transaction non terminée
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 79/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Il ne faut jamais oublier de terminerune transaction par commit() ou
rollback() car le résultat dépend dufournisseur de persistance et du SGBD
Page 80
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 80/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
IV. Identité des entités
Page 81
Clé primaire
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 81/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Une entité doit avoir un attribut qui correspond à laclé primaire dans la table associée
• La valeur de cet attribut ne doit jamais êtremodifiée par l’application dès que l’entitécorrespond à une ligne de la base
• Cet attribut doit être défini dans l’entité racined’une hiérarchie d’héritage (uniquement à cetendroit dans toute la hiérarchie d’héritage)
• Une entité peut avoir une clé primaire composite(pas recommandé)
Page 82
Annotation
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 82/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• L’attribut clé primaire est désigné par l’annotation@I d
• Pour une clé composite on utilise @Em b ed d ed I d ou @I d Class
Page 83
Type de la clé primaire
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 83/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Le type de la clé primaire (ou des champs d’une cléprimaire composée) doit être un des types
suivants:o type primitif Javao classe qui enveloppe un type primitif (Wrapper)
comme Integero java.lang.Stringo java.util.Date
o java.sql.Date
Ne pas utiliser les types numériques non entiers
Page 84
Génération automatique de clé
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 84/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Si la clé est de type numérique entier, l’annotation@GeneratedValue indique que la clé primaire
sera générée automatiquement par le SGBD
• Cette annotation peut avoir un attribut s t r a t egy
qui indique comment la clé sera générée (il prendses valeurs dans l’énumération Genera to rType )
Page 85
Types de génération
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 85/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• AUTO : le type de génération est choisi par le fournisseur depersistance, selon le SGBD (séquence, table,…) ; valeur pardéfaut
• SEQUENCE : une séquence est utilisée
• IDENTITY : une colonne de type IDENTITY est utilisée
• TABLE : une table qui contient la prochaine valeur del’identificateur est utilisée
• On peut aussi préciser le nom de la séquence ou de la tableavec l’attribut generator
Page 86
Générateurs d’identificateurs
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 86/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Les annotations @SequenceGenerator et@TableGenerator peuvent annoter l'identificateurde l'entité ou l'entité elle-même qui les utilise, oumême une autre entité
• Si le générateur ne sert que dans une seule classe,
il vaut mieux mettre l’annotation avec l’annotation@Id de la classe
• Sinon, une entrée dans un des fichiers XML deconfiguration de JPA, plutôt qu’une annotation,peut être un bon emplacement
Page 87
Exemple de générateur
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 87/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@SequenceGenerator(name = "emp_seq",
sequenceName = "emp_seq",
allocationSize = 10,initialValue = 600)
@SequenceGenerator(
name = "emp_seq",
sequenceName = "emp_seq",
allocationSize = 10,initialValue = 600)
Page 88
Exemple d'utilisation du générateur
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 88/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "emp_seq") public long getId() [
return id;
}
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "emp_seq")
public long getId() [
return id;
}
Page 89
Valeur d'incrément d'une séquence(à revoir)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 89/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Si une séquence utilisée par JPA est créée endehors de JPA, il faut que la valeur de pré-
allocation de JPA (égale à 50! par défaut)corresponde à la valeur d’incrémentation de laséquence ; on aura alors souvent ce typed’annotation :
@SequenceGenerator(
name="seq3",
sequenceName="seq3",initialValue="125,
allocationSize="20")
@SequenceGenerator(
name="seq3",
sequenceName="seq3",initialValue="125,
allocationSize="20")
Page 90
persist et id automatique
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 90/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• La spécification n’impose rien sur le moment où lavaleur de l’identificateur est mise dans l’objet géré
• La seule assurance est qu’après un flush dans labase de données (donc un commit) l’identificateur
aura déjà reçu sa valeur
• Avec TopLink et Oracle (et peut-être avec d’autres
produits), la valeur de l’identificateur est mise dèsl’appel de persist, sans attendre le commit, maisil est risqué pour la portabilité de l’utiliser
Page 91
Clé composite
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 91/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Pas recommandé, mais une clé primaire peut êtrecomposée de plusieurs colonnes
• Peut arriver quand la BD existe déjà ou quand laclasse correspond à une table association
(association M:N)
• 2 possibilités :
o @I d Class
o @Em b ed d ed I d et @Em b ed d ab le
Page 92
Classe pour la clé composite
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 92/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Dans les 2 cas, la clé primaire doit êtrereprésentée par une classe Java dont les
attributs correspondent aux composants de la cléprimaire
• La classe doit être public, posséder un constructeursans paramètre, être sérialisable et redéfinir equalset hashcode
Page 93
Première méthode: @IdClass
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 93/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• @IdClass correspond au cas où la classe entitécomprend plusieurs attributs annotés par @Id
• La classe entité est annotée par @IdClass quiprend en paramètre le nom de la classe clé
primaire
• La classe clé primaire n’est pas annotée (comme
@Embeddable) ; ses attributs ont les mêmes nomset mêmes types que les attributs annotés @Iddans la classe entité
Page 94
Exemple avec @IdClass
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 94/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@Entity
@IdClass(EmployePK.class)
public class Employe {
@Id
private String nom;
@Id
Date dateNaissance;
...}
// Classe PK sans annotations
public class EmployePK {
private String nom; private Date dateNaissance;
...
}
@Entity
@IdClass(EmployePK.class)
public class Employe {
@Id private String nom;
@Id
Date dateNaissance;
...
}
// Classe PK sans annotations
public class EmployePK {
private String nom;
private Date dateNaissance;...
}
Page 95
Recherche par clés composite
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 95/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
1. Méthode f i nd : Il faut crééer une instance de laclasse PK et la passer comme deuxième argument
à la méthode find.
public Employee findEmployee(String nom, Date d) {
return em.find(Employee.class,
new EmployeeId(nom, d));
}
public Employee findEmployee(String nom, Date d) {
return em.find(Employee.class,
new EmployeeId(nom, d));
}
Page 96
Recherche par clés composite
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 96/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
2 . JPQL: utiliser directement les champs définis dansl’Entity Employee.
public Employee findEmployee(String nom, Date d) {
Query q = em.createQuery("SELECT e " +
"FROM Employee e " + "WHERE e.nom = ?1 AND e.dateNaissance = ?2");
return (Employee)q.setParameter(1, nom)
.setParameter(2, d)
.getSingleResult();
}
public Employee findEmployee(String nom, Date d) {
Query q = em.createQuery("SELECT e " +
"FROM Employee e " +
"WHERE e.nom = ?1 AND e.dateNaissance = ?2");
return (Employee)q.setParameter(1, nom)
.setParameter(2, d)
.getSingleResult();
}
Page 97
Deuxième méthode: @EmbeddedId
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 97/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• @EmbeddedId correspond au cas où la classeentité comprend un seul attribut annoté
@EmbeddedId
• La classe clé primaire est annoté par
@Embeddable
Attention:
Le type d’accès (par champs ou propriétés) de laclasse « embeddable » doit être le même que celuide l’entité dont la clé primaire est définie
Page 98
@ i@Entity
Exemple avec @EmbeddedId
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 98/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@Entity
public class Employe {
@EmbeddedId
private EmployePK id;
...
}
@Embeddable
public class EmployePK {
private String nom;
private Date dateNaissance;...
}
@Entity
public class Employe {
@EmbeddedId
private EmployePK id;...
}
@Embeddable public class EmployePK {
private String nom;
private Date dateNaissance;
...
}
Page 99
Recherche par clés composite
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 99/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
1. Méthode f i nd : Il faut créer une instance de laclasse PK et la passer comme deuxième argument
à la méthode find.
public Employee findEmployee(String nom, Date d) {
return em.find(Employee.class,
new EmployeeId(nom, d));
}
public Employee findEmployee(String nom, Date d) {
return em.find(Employee.class,
new EmployeeId(nom, d));
}
Page 100
à é
Recherche par clés composite
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 100/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
2 . EJBQL: different % à la méthode IdClass :
Il faut traverser la classe PK.
public Employee findEmployee(String nom, Date d) {
Query q = em.createQuery("SELECT e " + "FROM Employee e " +
"WHERE e.id.nom = ?1 AND e.id.dateNaissance = ?2");
Return (Emplyee)q.setParameter(1, nom).setParameter(2, d)
.getSingleResult();
}
public Employee findEmployee(String nom, Date d) {
Query q = em.createQuery("SELECT e " +
"FROM Employee e " +
"WHERE e.id.nom = ?1 AND e.id.dateNaissance = ?2");
Return (Emplyee)q.setParameter(1, nom)
.setParameter(2, d)
.getSingleResult();
}
Page 101
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 101/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
V. Associations
Page 102
ê
Généralités
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 102/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Une association peut être uni ou bidirectionnelle• Elle peut être de type 1:1, 1:N, N:1 ou M:N
• Les associations doivent être indiquées par uneannotation sur la propriété correspondante, pourque JPA puisse les gérer correctement
• Exemple:
@ManyToOne
public Departement getDepartement() {
...
}
@ManyToOne
public Departement getDepartement() {
...}
Page 103
Représentation des associations 1:N et M:N
Représentation des associations1:N et M:N
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 103/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Représentation des associations 1:N et M:N
• Elles sont représentées par des collections ou mapsqui doivent être déclarées par un des typesinterface suivants (de java.util) :o Collection
o Set
o List
o Map
• Les variantes génériques sont conseillées ; parexemple Collection<Employe>
Page 104
• Le plus souvent Col lect ion sera utilisé
Types à utiliser
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 104/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Le plus souvent Col lect ion sera utilisé
• Set peut être utile pour éliminer les doublons
• Les types concrets, tels que HashSet ou Ar rayL is t , nepeuvent être utilisés que pour des entités « nouvelles » ; dès
que l’entité est gérée, les types interfaces doivent êtreutilisés (ce qui permet au fournisseur de persistance d’utiliserson propre type concret)
• List peut être utilisé pour conserver un ordre mais nécessitequelques précautions
Page 105
L’ d d’ li t ' t é i t
Ordre dans les collections
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 105/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• L’ordre d’une liste n'est pas nécessairementpréservé dans la base de données
• De plus, l’ordre en mémoire doit être maintenu parle code (pas automatique)
• Tout ce qu’on peut espérer est de récupérer lesentités associées dans la liste avec un certain ordre
lors de la récupération dans la base, en utilisantl’annotation @OrderBy
Page 106
• Cette annotation indique dans quel ordre sont récupérées les
@OrderBy
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 106/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Cette annotation indique dans quel ordre sont récupérées lesentités associées
• Il faut préciser un ou plusieurs attributs qui déterminentl'ordre
• Chaque attribut peut être précisé par ASC ou DESC (ordreascendant ou descendant); ASC par défaut
• Les différents attributs sont séparés par une virgule
• Si aucun attribut n'est précisé, l'ordre sera celui de la cléprimaire
Page 107
Exemples
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 107/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@Entity
public class Departement {...
@OneToMany(mappedBy="departement")
@OrderBy("nomEmploye")
public List<Employe> getEmployes() {
...
@OrderBy("poste DESC, nomEmploye ASC")
@Entity
public class Departement {
...
@OneToMany(mappedBy="departement")
@OrderBy ("nomEmploye") public List<Employe> getEmployes() {
...
@OrderBy ("poste DESC, nomEmploye ASC")
Page 108
• Le développeur est responsable de la gestion
Associations bidirectionnelles
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 108/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Le développeur est responsable de la gestioncorrecte des 2 bouts de l’association
• Par exemple, si un employé change dedépartement, les collections des employés des
départements concernés doivent être modifiées
• Un des 2 bouts est dit « propriétaire » de
l’association
Page 109
• Pour les associations autres que M:N ce bout
Bout propriétaire
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 109/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Pour les associations autres que M:N ce boutcorrespond à la table qui contient la clé étrangère
qui traduit l’association
• Pour les associations M:N le développeur peut
choisir arbitrairement le bout propriétaire
• L’autre bout (non propriétaire) est qualifié par
l’attribut mappedBy qui donne le nom de l’attributdans le bout propriétaire qui correspond à la mêmeassociation
Page 110
D l l E l• Dans la classe Employe :
Exemple
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 110/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Dans la classe Employe :
@ManyToOne
public Departement getDepartement() {
return departement;
}
• Dans la classe Departement :
@OneToMany(mappedBy="departement")
public Collection<Employe> getEmployes() {return employes;
}
p y
@ManyToOne
public Departement getDepartement() {return departement;
}
• Dans la classe Departement :
@OneToMany( mappedBy ="departement")
public Collection<Employe> getEmployes() {
return employes;
}
Page 111
• Pour faciliter la gestion des 2 bouts d'une
Meilleure pratique:gestion de l’association
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 111/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Pour faciliter la gestion des 2 bouts d uneassociation le code peut comporter une méthode
qui effectue tout le travail• En particulier, dans les associations 1-N, le bout«1» peut comporter ce genre de méthode (dans laclasse Departement d’une associationdépartement-employé) :
public void ajouterEmploye(Employe e) {
this.employes.add(e);e.setDept(this);
}
public void ajouterEmploye(Employe e) {
this.employes.add(e);e.setDept(this);
}
Page 112
• Cette annotation donne le nom de la colonne clé
Annotation @JoinColumn
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 112/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Cette annotation donne le nom de la colonne cléétrangère qui représente l'association dans le
modèle relationnel
• Elle doit être mise du côté propriétaire (qui
contient la clé étrangère)
• Sans cette annotation, le nom est défini par défaut
de la manière suivante:
<entité_but>_<clé_primaire_entité_but>
Page 113
• Pour l'association qui détermine le département d'un
Exemple
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 113/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Pour l association qui détermine le département d unemployé
o Par défaut, la colonne clé étrangère placée dans la tableEMPLOYE s'appellera Departement_ID
o Pour changer ce nom (dans la classe Employe) voici unexemple:
@ManyToOne
@JoinColumn(name="DEPT_ID")
public Departement getDepartement() {
@ManyToOne
@JoinColumn(name="DEPT_ID")
public Departement getDepartement() {
Entité but Clé primaire Entité but
Page 114
• L’annotation @JoinColumns permet d’indiquer le
Annotation @JoinColumns
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 114/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
L annotation @JoinColumns permet d indiquer lenom des colonnes qui constituent la clé étrangère
dans le cas où il y en a plusieurs (si la clé primaireréférencée contient plusieurs colonnes)
• En ce cas, les annotations @JoinColumn doiventnécessairement comporter un attributreferencedColumnName pour indiquer quellecolonne est référencée (parmi les colonnes de laclé primaire référencée)
Page 115
Exemple
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 115/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@JoinColumns({
@JoinColumn(name="n1",
referencedColumnName="c1"),
@JoinColumn(name="n2",
referencedColumnName="c2")
})
@JoinColumns({
@JoinColumn(name="n1",
referencedColumnName="c1"),
@JoinColumn(name="n2",
referencedColumnName="c2")
})
Page 116
• Afin de faciliter le maintien de cette cohérence, il
Persistance automatique
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 116/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Afin de faciliter le maintien de cette cohérence, ilest possible d’indiquer à JPA que les objets
associés à un objet persistant doivent êtreautomatiquement rendus persistants
• Pour cela il suffit d’ajouter un attribut « cascade »dans les informations de mapping de l’association
Page 117
• Les annotations qui décrivent les associations entre
Attribut cascade
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 117/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
qobjets peuvent avoir un attribut cascade pour
indiquer que certaines opérations du GE doiventêtre appliquées aux objets associés
• Ces opérations sont PERSIST, REMOVE,REFRESH et MERGE ; ALL correspond à toutesces opérations
• Par défaut, aucune opération n’est appliquéetransitivement
Page 118
Exemples
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 118/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
•
@OneToMany(cascade=CascadeType.PERSIST)
• @OneToMany(
cascade={CascadeType.PERSIST,
CascadeType.MERGE})
• @OneToMany(
cascade=CascadeType.PERSIST)
• @OneToMany(
cascade={CascadeType.PERSIST,
CascadeType.MERGE})
Page 119
Direction des relations (directionality)
• Unidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 119/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
On ne peut aller que du bean A vers le bean B
• Bidirectionnelle On peut aller du bean A vers le bean B et inversement
Page 120
• Annotation @OneToOne
Association 1:1
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 120/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Représentée par une clé étrangère ajoutée dans latable qui correspond au côté propriétaire
• Exemple :@OneToOne
public Adresse getAdresse() {
…
}
@OneToOne
public Adresse getAdresse() {
…}
Page 121
Association 1:1 Unidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 121/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Order Shipment1 1
Navigabilité
unidirectionnelle
Navigabilité
unidirectionnelle
Page 122
Association 1:1 Unidirectionnelle, le bean Order
@Entity(name="OrderUni")
public class Order implements Serializable {
@Entity(name="OrderUni") public class Order implements Serializable {
private int id;
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 122/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
p p {
private int id;
private String orderName;
private Shipment shipment;
public Order() {
id = (int)System.nanoTime();
}@Id
public int getId() {
return id;
}
@OneToOne(cascade={CascadeType.PERSIST}) public Shipment getShipment() {
return shipment;
}
private int id;
private String orderName;
private Shipment shipment;
public Order() {
id = (int)System.nanoTime();
}
@Id
public int getId() {
return id;
}
@OneToOne(cascade={CascadeType.PERSIST}) public Shipment getShipment() {
return shipment;
}
Page 123
@Entity(name="ShipmentUni")
public class Shipment implements Serializable {
@Entity(name="ShipmentUni") public class Shipment implements Serializable {
private int id;
Association 1:1 Unidirectionnelle, le bean Shipment
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 123/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
private int id;
private String city;
private String zipcode;
public Shipment() {
id = (int)System.nanoTime();
}
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private int id;
private String city;
private String zipcode;
public Shipment() {
id = (int)System.nanoTime();
}
@Id
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
}
Page 124
Association 1:1, résultat mapping
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 124/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Nom pardéfaut
(Automatique)
Nom pardéfaut
(Automatique)
Page 125
public static void editOrders(EntityManagerFactory factory) {
()
public static void editOrders(EntityManagerFactory factory) {
EntityManager manager = factory.createEntityManager();
Association 1:1 Unidirectionnelle, code test
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 125/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
EntityManager manager = factory.createEntityManager();
Query q = manager.createQuery("SELECT o FROM OrderUni o");//Collection l = q.getResultList();
for (Object o : q.getResultList()) {
Order order = (Order)o;
System.out.println("Order "+order.getId()+":"+order.getOrderName());
System.out.println("\tShipment details:"+ order.getShipment().getCity()+""+ order.getShipment().getZipcode());
}
}
y g g y y g ();
Query q = manager.createQuery("SELECT o FROM OrderUni o");
//Collection l = q.getResultList();
for (Object o : q.getResultList()) {
Order order = (Order)o;
System.out.println("Order "+order.getId()+":"+order.getOrderName());
System.out.println("\tShipment details:
"+ order.getShipment().getCity()+""+ order.getShipment().getZipcode());
}
}
Page 126
Association 1:1 Bidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 126/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Order Shipment1 1
Navigabilité
bidirectionnelle
Navigabilité
bidirectionnelle
Page 127
@Entity(name="ShipmentBid") public class Shipment implements Serializable {
i t i t id
@Entity(name="ShipmentBid") public class Shipment implements Serializable {
private int id;
Version i irectionne e:(on modifie Shipment)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 127/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
private int id;
private String city;
private String zipcode;Private Order order;
public Shipment() {
id = (int)System.nanoTime();
}
…………
@OneToOne(mappedBy="shipment")
public Order getOrder() {return order;
}
}
private String city;
private String zipcode;
Private Order order;
public Shipment() {
id = (int)System.nanoTime();
}…………
@OneToOne(mappedBy="shipment")
public Order getOrder() {
return order;
}
}
Page 128
public static void editShipments(EntityManagerFactory factory){
EntityManager manager = factory createEntityManager();
public static void editShipments(EntityManagerFactory factory){
EntityManager manager = factory.createEntityManager();
Association 1:1 Bidirectionnelle, code test
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 128/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
EntityManager manager = factory.createEntityManager();
Query q = manager.createQuery("SELECT s FROM ShipmentBid s");
for (Object o : q.getResultList()) {
Shipment shipment = (Shipment)o;
System.out.println("Shipment: "+shipment.getCity()+""+shipment.getZipcode());
System.out.println("\tOrder details:"+ shipment.getOrder().getOrderName());
}
}
Query q = manager.createQuery("SELECT s FROM ShipmentBid s");
for (Object o : q.getResultList()) {
Shipment shipment = (Shipment)o;
System.out.println("Shipment: "+shipment.getCity()+""+shipment.getZipcode());
System.out.println("\tOrder details:
"+ shipment.getOrder().getOrderName());}
}
Page 129
• Annotations @OneToMany et @ManyToOne
R é é lé é è d l bl
Associations 1:N et N:1
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 129/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Représentée par une clé étrangère dans la table
qui correspond au côté propriétaire(obligatoirement le côté « Many »)
class Employe {...
@ManyToOne
public Departement getDepartement()
{
...
}
}
class Employe {
...
@ManyToOne
public Departement getDepartement()
{
...}
}
class Departement {
...
@OneToMany(mappedBy="departement")
public List<Employe> getEmployes() {
...
}
}
class Departement {...
@OneToMany (mappedBy="departement")
public List<Employe> getEmployes() {
...
}
}
Page 130
Association 1:N
Commande Ligne de
1 *
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 130/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Commandecommande
Sciété Employé
1 *
Client Commande
1 *
Page 131
• Le GE génère automatiquement une table de jointure
Association 1:N Unidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 131/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
j
Page 132
Associaltion 1:N exemple
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 132/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 133
Associaltion 1:N exemple
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 133/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 134
Exemple de code qui insère des compagnies
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 134/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 135
Exemple de code qui insère des compagnies
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 135/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 136
Exemple de client
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 136/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 137
public class Dept {
...
public class Dept {...
1:N unidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 137/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@OneToMany
@JoinTable(name="DEPT_EMP",
joinColumns=
@JoinColumn(name="DEPT_ID"),inverseJoinColumns=
@JoinColumn(name="EMP_ID"))
private Collection<Employe> employes;...
}
@OneToMany
@JoinTable(name="DEPT_EMP",
joinColumns=
@JoinColumn(name="DEPT_ID"),
inverseJoinColumns=
@JoinColumn(name="EMP_ID"))
private Collection<Employe> employes;...
}
Page 138
• Le GE ne génrère pas une table de jointure. Ilgénére une clé étrangère dans la table côté *
Association 1:N Bidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 138/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 139
Version bidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 139/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 140
Version bidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 140/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 141
Version bidirectionnelle
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 141/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Page 142
• Annotation @ManyToMany
• Représentée par une table d’association
Association M:N
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 142/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
p p
Page 143
• Les valeurs par défaut :
Association M:N (1)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 143/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
o le nom de la table association est laconcaténation des 2 tables, séparées par « _ »
o les noms des colonnes clés étrangères sont lesconcaténations de la table référencée, de « _ »et de la colonne « Id » de la table référencée
Page 144
• Le côté propriétaire est arbitraire
Association M:N (2)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 144/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Si les valeurs par défaut ne conviennent pas, lecôté propriétaire doit comporter une annotation@JoinTable
• L’autre côté doit toujours comporter l’attributm ap p ed By
Page 145
• Donne des informations sur la table association qui vareprésenter l’association
@JoinTable
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 145/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Attribut n am e donne le nom de la table
• Attribut j o i n Col u m n s donne les noms des colonnes de latable qui référencent les clés primaires du côté propriétairede l’association
• Attribut in v er seJo in Colu m n s donne les noms des colonnes
de la table qui référencent les clés primaires du côté qui n’estpas propriétaire de l’association
Page 146
Exemple1(clés simples)
Côtéprop.
Côtéprop.
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 146/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@ManyToMany(mappedBy="projets")
public Collection<Employee> getEmployees() {
@ManyToMany(mappedBy="projets")
public Collection<Employee> getEmployees() {
ClasseProject
(côté inv.)
@ManyToMany
@JoinTable(name="EMP_PROJ"
joinColumns = @JoinColumn(name="EMP_ID")
inverseJoinColumns = @JoinColumn(name="PROJ_ID")
)
public Collection<Projet> getProjects() {
@ManyToMany
@JoinTable(
name="EMP_PROJ"
joinColumns = @JoinColumn(name="EMP_ID")
inverseJoinColumns = @JoinColumn(name="PROJ_ID")
)
public Collection<Projet> getProjects() {
ClasseEmployee
(côté prop.)
Côtéinv.
Côté
inv.
Page 147
Exemple2 (clés composite)
ô é
Côtéinv.
Côtéinv.
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 147/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@Id private String country;
@Id
@Column(name="EMP_ID") private int id;
@ManyToMany
@JoinTable( name="EMP_PROJECT",
joinColumns={
@JoinColumn(name="EMP_COUNTRY", referencedColumnName="COUNTRY"),
@JoinColumn(name="EMP_ID", referencedColumnName="EMP_ID")},
inverseJoinColumns=
@JoinColumn(name="PROJECT_ID"))
private Collection<Project> projects
@Id private String country;
@Id
@Column(name="EMP_ID")
private int id;
@ManyToMany
@JoinTable( name="EMP_PROJECT",
joinColumns={
@JoinColumn(name="EMP_COUNTRY", referencedColumnName="COUNTRY"),
@JoinColumn(name="EMP_ID", referencedColumnName="EMP_ID")},
inverseJoinColumns=
@JoinColumn(name="PROJECT_ID"))
private Collection<Project> projects
C l a s s eE m pl o
y e e
( c ô t é pr o p. )
Côté
prop.
Côtéprop.
Page 148
• Une association M:N peut porter une information
Association M:N avec informationportée par l'association
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 148/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Exemple :Association entre les employés et les projets Unemployé a une (et une seule) fonction dans chaque
projet auquel il participe
• En ce cas, il n'est pas possible de traduire
l'association en ajoutant 2 collections (ou maps)comme il vient d'être décrit
Page 149
• L'association sera traduite par une classeassociation
Classe association pour uneassociation M:N
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 149/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• 2 possibilités pour cette classe, suivant qu'ellecontient ou non un attribut identificateur (@Id)unique
• Le plus simple est de n'avoir qu'un seul attributidentificateur
Page 150
• Association entre les employés et les projets
Exemple - 1 identificateur
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 150/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Cas d'un identificateur unique : la classeassociation contient les attributs id (int), employe( Employe), projet ( Projet) et fonction (String)
• L'attribut id est annoté par @Id
• Les attributs employe et projet sont annotés par@ManyToOne
Page 151
• Exemple - 1 identificateur
• Si le schéma relationnel est généré d’après les informations
Exemple - 1 identificateur
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 151/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
S e sc é a e at o e est gé é é d ap ès es o at o s
de mapping par les outils associés au fournisseur depersistance, on peut ajouter une contrainte d'unicité sur(EMPLOYE_ID, PROJET_ID) qui traduit le fait qu'un employéne peut avoir 2 fonctions dans un même projet :
@Entity
@Table(uniqueConstraints=
@UniqueConstraint(columnNames =
{"EMPLOYE_ID","PROJET_ID"}) public class Participation {
@Entity
@Table(uniqueConstraints=
@UniqueConstraint(columnNames =
{"EMPLOYE_ID","PROJET_ID"}) public class Participation {
Page 152
• Si la base de données existe déjà, il sera fréquentde devoir s'adapter à une table association quicontient les colonnes suivantes (pas de colonne
Exemple - 2 identificateurs (1)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 152/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
contient les colonnes suivantes (pas de colonne
id):o employe_id, clé étrangère vers EMPLOYEo projet_id, clé étrangère vers PROJETo fonction
• et qui a (employe_id, projet_id) comme cléprimaire
Page 153
• Dans ce cas, la solution est plus complexe, et pastoujours portable dans l'état actuel de laspécification JPA
Exemple - 2 identificateurs (2)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 153/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
spécification JPA
• La solution donnée dans les transparents suivantsconvient pour TopLink et Hibernate, les 2fournisseurs de persistance les plus utilisés ; ellen’a pas été testée sur d’autres fournisseurs
Page 154
• La difficulté vient de l'écriture de la classeParticipation
Exemple - 2 identificateurs
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 154/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• L'idée est de dissocier la fonction d'identificateurdes attributs employeId et projetId de leur rôledans les associations avec les classes Projet etEmploye
Page 155
• Pour éviter les conflits au moment du flush, lescolonnes qui correspondent aux identificateurs sontmarqués non modifiables ni insérables (pas de
Exemple - 2 identificateurs
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 155/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
marqués non modifiables ni insérables (pas de
persistance dans la BD)
• En effet, leur valeur sera mise par le mapping desassociations 1-N vers Employe et Projet qui seratraduite par 2 clés étrangères
Page 156
@Entity public class Employe {@Id public int getId() { ... }
@OneToMany(mappedBy="employe")
public Collection<Participation>
@Entity public class Employe {
@Id public int getId() { ... }
@OneToMany(mappedBy="employe")
public Collection<Participation>
Classes Employe et Projet
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 156/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
public Collection<Participation>
getParticipations() { ... }
. . .
}
getParticipations() { ... }. . .
}
@Entity public class Projet {
@Id public int getId() { ... }
@OneToMany(mappedBy="projet")
public Collection<Participation> getParticipations() {
...
}
. . .
}
@Entity public class Projet {@Id public int getId() { ... }
@OneToMany(mappedBy="projet")
public Collection<Participation> getParticipations() {
...}
. . .
}
Page 157
• On peut utiliser une classe « Embeddable » ou une« IdClass » pour représenter la clé composite deParticipation
Classe Participation(2 choix pour Id)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 157/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
Participation
• Le code suivant utilise une IdClass
Page 158
@Entity
@IdClass(ParticipationId.class)
public class Participation {
@Entity
@IdClass(ParticipationId.class)
public class Participation {
Classe Participation (Id)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 158/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
public class Participation {
// Les identificateurs "read-only"
@Id
@Column(name="EMPLOYE_ID",
insertable="false", updatable="false") public int getEmployeId() { … }
@Id
@Column(name="PROJET_ID",insertable="false", updatable="false")
public int getProjetId() { … }
// Les identificateurs "read-only"@Id
@Column(name="EMPLOYE_ID",
insertable="false", updatable="false")
public int getEmployeId() { … }
@Id
@Column(name="PROJET_ID",
insertable="false", updatable="false")
public int getProjetId() { … }
Page 159
private Employe employe; private Employe employe;
private long employeId;
Classe Participation (champs)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 159/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
private long employeId; private Projet projet;
private long projetId;
private String fonction; public Participation() { }
private long employeId;
private Projet projet;
private long projetId;
private String fonction; public Participation() { }
Page 160
• Il faut éviter la possibilité qu’un bout seulement del’association soit établie et pour cela, il faut qu’uneseule classe s’en charge
Établir une association
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 160/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
g
• Pour cela, on peut faire gérer l’association entièrepar Projet, par Employe ou par Participation
• Le transparent suivant montre comment la fairegérer par le constructeur de Participation
Page 161
public Participation() { } // Pour JPA
public Participation(Employee employe,
Projet projet,
String fonction) {
public Participation() { } // Pour JPA public Participation(Employee employe,
Projet projet,
String fonction) {
Participation (constructeurs)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 161/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
String fonction) {
this.employeId = employe.getId();
this.projetId = projet.getId();
// gestion de l’association avec Employee
this.employe = employe;
employe.getParticipations.add(this);// gestion de l’association avec Project
this.projet = projet;
projet.getParticipations.add(this);
this.fonction = fonction;
}
this.employeId = employe.getId();this.projetId = projet.getId();
// gestion de l’association avec Employee
this.employe = employe;
employe.getParticipations.add(this);
// gestion de l’association avec Project
this.projet = projet;
projet.getParticipations.add(this);
this.fonction = fonction;}
Page 162
// Les associations
@ManyToOne
// Les associations
@ManyToOne
public Employe getEmploye() {
Participation (associations)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 162/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
public Employe getEmploye() {return employe;
}
@ManyToOne
public Projet getProjet() {
return projet;
}
. . .
}
p p y g p y () {
return employe;
}
@ManyToOne
public Projet getProjet() {
return projet;
}
. . .}
Page 163
public class ParticipationId implementsSerializable {
private int employeId;
public class ParticipationId implementsSerializable {
private int employeId;
Classe ParticipationId
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 163/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
p p y ;
private int projetId;
public int getEmployeId() { ... }
public void setEmployeId(int employeId)
{ ... } public int getProjetId() { ... }
public void setProjetId(int projetId)
{ ... }
// Redéfinir aussi equals et hasCode
private int projetId; public int getEmployeId() { ... }
public void setEmployeId(int employeId)
{ ... }
public int getProjetId() { ... }
public void setProjetId(int projetId)
{ ... }
// Redéfinir aussi equals et hasCode
Page 164
• Lorsqu’une entité est récupérée depuis la base dedonnées par une requête (Query) ou par un find,est-ce que les entités associées doivent être elles
Récupération des entités associées
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 164/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
aussi récupérées ?
• Si elles sont récupérées, est-ce que les entitésassociées à ces entités doivent elles aussi êtrerécupérées ?
• On voit que le risque est de récupérer un trèsgrand nombre d’entités qui ne seront pas utilespour le traitement en cours
Page 165
• JPA laisse le choix de récupérer ou non
immédiatement les entités associées, suivant lescirconstances
EAGER ou LAZY
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 165/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
• Il suffit de choisir le mode de récupération del’association (LAZY ou EAGER)
• Une requête sera la même, quel que soit le modede récupération
• Dans le mode LAZY les données associées ne sontrécupérées que lorsque c’est vraiment nécessaire
Page 166
• Dans le cas où une entité associée n’est pasrécupérée immédiatement, JPA remplace l’entitépar un « proxy », objet qui permettra de récupérer
Récupération retardée (LAZY)
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 166/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
l’entité plus tard si besoin est
• Ce proxy contient la clé primaire qui correspond à
l’entité non immédiatement récupérée
• Il est possible de lancer une requête avec unerécupération immédiate, même si une associationest en mode LAZY (join fetch étudié plus loin)
Page 167
• Par défaut, JPA ne récupère immédiatement queles entités associées par des associations dont lebut est « One » (une seule entité à l’autre bout) :
Comportement par défaut de JPA
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 167/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
OneToOne et ManyToOne (mode EAGER)
• Pour les associations dont le but est « Many » (une
collection à l’autre bout), OneToMany etManyToMany, par défaut, les entités associées nesont pas récupérées immédiatement (mode LAZY)
Page 168
• L’attribut fetch d’une association permet d’indiquerune récupération immédiate des entités associées(FetchType.EAGER) ou une récupération retardée
Indiquer le type de récupérationdes entités associées
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 168/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
( FetchType.LAZY) si le comportement par défautne convient pas
• Exemple :
@OneToMany(mappedBy="departement",
fetch=FetchType.EAGER)
public Collection<Employe> getEmployes()
@OneToMany(mappedBy="departement",
fetch=FetchType.EAGER)
public Collection<Employe> getEmployes()
Page 169
• Les attributs aussi peuvent être récupérés en mode «retardé»
• Le mode de récupération par défaut est le mode EAGER pour
Mode de récupérationdes attributs
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 169/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
les attributs (ils sont chargés en même temps que l’entité)
• Si un attribut est d’un type de grande dimension (LOB), ilpeut aussi être marqué par
@Basic(fetch=FetchType.LAZY) (à utiliser avecparcimonie)
• Cette annotation n’est qu’une suggestion au GE, qu’il peut nepas suivre
Page 170
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 170/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
VI. Héritage
Page 171
• A ce jour, les implémentations de JPAdoivent obligatoirement offrir 3 stratégies
Stratégies
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 171/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
pour la traduction de l’héritage :o une seule table pour une hiérarchie d’héritage(SINGLE_TABLE)
o une table par classe ; les tables sont jointespour reconstituer les données (JOINED)o une table distincte par classe concrète
(TABLE_PER_CLASS)
Page 172
• Sans doute la stratégie la plus utilisée
• Valeur par défaut de la stratégie de traduction de
Une table par hiérarchie
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 172/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
l’héritage
• Elle est performante et permet le polymorphisme
• Mais elle induit beaucoup de valeurs NULL dans les
colonnes si la hiérarchie est complexe
Page 173
Une table par hiérarchie
@Entity
@Table(name="Animal")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public c lass Animal {
@Id i t i t id
@Entity
@Table(name="Animal")@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class Animal {
@Id private int id;
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 173/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
@Id private int id;@Column(name="AVG_WEIGHT")
private int averageWeight;
...
}
@Entity@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
publ ic class Dog extends Animal{
@Column(name="BREED")private String breed;
...
}
@Column(name="AVG_WEIGHT")
private int averageWeight;
...
}
@Entity@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
publ ic class Dog extends Animal{
@Column(name="BREED")private String breed;
...
}
Page 174
Mode de récupérationdes attributs
create table Animal(
ID Number,
TYPE varchar(255),
AVG WEIGHT N b
create table Animal
(
ID Number,
TYPE varchar(255),
AVG WEIGHT N b
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 174/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
AVG_WEIGHT Number,
BREED varchar(255)
);
AVG_WEIGHT Number,BREED varchar(255)
);
Page 175
Une table par classe dérivée
@Entity@Inheritance(strategy=InheritanceType.JOINED)
public class Animal{
@Id private int id;
@Column(name="AVG_WEIGHT")
private int averageWeight;
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Animal{
@Id private int id;
@Column(name="AVG_WEIGHT")
private int averageWeight;
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 175/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
private int averageWeight;
...
}
@Entity@InheritanceJoinColumn(name="DOGGY_ID")
publ ic class Dog extends Animal{
@Column(name="BREED")
private String breed;...
}
private int averageWeight;...
}
@Entity@InheritanceJoinColumn(name="DOGGY_ID")
public class Dog extends Animal{
@Column(name="BREED")
private String breed;
...}
Page 176
Une table par classe dérivée
create table Animal(
ID Number,
TYPE varchar(255),
AVG WEIGHT N b
create table Animal
(
ID Number,
TYPE varchar(255),
AVG WEIGHT Number
5/12/2018 JavaEE CouchePersistance JPA Esprit - slidepdf.com
http://slidepdf.com/reader/full/javaee-couchepersistance-jpa-esprit 176/176
Esprit 2009/ 2010 Adel ELJ (Architecte J2EE)
AVG_WEIGHT Number
);
create table Doggy(
DOGGY_ID Number,
BREED varchar(255));
AVG_WEIGHT Number );
create table Doggy(
DOGGY_ID Number,
BREED varchar(255));