176
 4.1: Couche Persistance EJB3/JPA Formation Java EE 5 / Spring Par Adel ELJ, Architecte J2EE

JavaEE CouchePersistance JPA Esprit

  • Upload
    smjojo

  • View
    188

  • Download
    0

Embed Size (px)

Citation preview

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