Vous êtes sur la page 1sur 43

Plan de la partie 1

(Java Persistence API) - Partie 1


Universit de Nice - Sophia Antipolis
Version 2.11 4/12/11 Richard Grin

JPA 2.0

Prsentation de JPA Entits persistantes Gestionnaire dentits Identit des entits Associations entre entits Complments sur les associations (persistance et rcupration des entits associes, ordre des listes, orphelins) Hritage entre entits
R. Grin JPA page 2

EJB
Java EE (Enterprise Edition) est une plateforme de dveloppement et un ensemble de spcifications pour le dveloppement dapplications dentreprises multi-tiers EJB (Enterprise JavaBeans) fait partie de Java EE Dfinit un cadre (framework) pour lutilisation de composants mtier rutilisables par des serveurs dapplications Java

Prsentation de JPA

R. Grin

JPA

page 3

R. Grin

JPA

page 4

JPA
JPA (Java persistence API) est la partie de la spcification EJB qui concerne la persistance des composants dans une base de donnes relationnelle JPA peut tre utilis par toutes les applications Java, mme en dehors de Java EE Cest lAPI ORM (Object-Relational Mapping) standard pour la persistance des objets Java JPA 2.0 fait partie de EJB 3.1, inclus dans Java EE 6
R. Grin JPA page 5

Quelques nouveauts de JPA 2.0 par rapport JPA 1


API criteria pour crire des requtes sans utiliser le langage JPQL, avec vrifications la compilation Listes ordonnes dans la BD Collections persistantes dlments de type basic (qui ne correspondent pas une association entre entits) et dembeddable Facilits pour des mappings avec des cls primaires qui contiennent des cls trangres
R. Grin JPA page 6

Principales proprits de JPA


Pas de code spcial li la persistance implmenter dans le classes ; les objets POJO (Plain Old Java Object) peuvent tre persistants Des appels simples de haut niveau permettent de grer la persistance, tels que persist(objet) pour rendre un objet persistant ; pas dappel de bas niveau comme avec JDBC Les donnes de la base peuvent tre accdes avec une vision objet (pas relationnelle)

Spcification JPA
Pour plus de prcisions, lire la spcification ladresse http://jcp.org/aboutJava/communityprocess/pfd/js r317/index.html

R. Grin

JPA

page 7

R. Grin

JPA

page 8

Avertissement
JPA est le plus souvent utilis dans le contexte dun serveur dapplications (Java EE) Ce cours tudie lutilisation de JPA par une application autonome, en dehors de tout serveur dapplications Quelques informations sur lutilisation de JPA avec un serveur dapplications sont donnes dans ce cours mais sans entrer dans les dtails Les diffrences sont essentiellement lies la faon dobtenir un gestionnaire dentits et aux transactions ; presque tout le reste est identique
R. Grin JPA page 9

Fournisseur de persistance
Comme pour JDBC, lutilisation de JPA ncessite un fournisseur de persistance qui implmente les classes et mthodes de lAPI GlassFish est limplmentation de rfrence de la spcification EJB 3 EclipseLink est limplmentation de rfrence de la spcification JPA 2.0 (http://www.eclipse.org/eclipselink/) Dautres implmentations : Hibernate Entity Manager, OpenJPA, BEA Kodo
R. Grin JPA page 10

Entits
Les classes dont les instances peuvent tre persistantes sont appeles des entits dans la spcification de JPA Le dveloppeur indique quune classe est une entit en lui associant lannotation @Entity Ne pas oublier dimporter javax.Persistence.Entity dans les classes entits (importations semblables pour toutes les annotations)
R. Grin JPA page 11

@Entity
Cette annotation peut avoir un attribut name qui donne le nom de lentit (rarement utilis) Par dfaut, le nom de lentit est le nom terminal (sans le nom du paquetage) de la classe Exemple : @Entity(name="dept") public class Departement {

R. Grin

JPA

page 12

Vocabulaire
Dans la suite de ce cours et quand il ny aura pas ambigut, entit dsignera soit une classe entit, soit une instance de classe entit, suivant le contexte

Exemple dentit identificateur et attributs


@Entity public class Departement { @Id @GeneratedValue private int id; private String nom; private String lieu;

R. Grin

JPA

page 13

R. Grin

JPA

page 14

Exemple dentit constructeurs


/** * Constructeur sans paramtre obligatoire. */ public Departement() { } public Departement(String nom, String lieu) { this.nom = nom; this.lieu = lieu; }
R. Grin JPA page 15

Exemple dentit une association


Lassociation inverse dans la classe Employe @OneToMany(mappedBy="dept") private Collection<Employe> employes = new ArrayList<Employe>(); public Collection<Employe> getEmployes() { return employes; } public void addEmploye(Employe emp) { employes.add(emp); }

R. Grin

JPA

page 16

Fichiers de configuration XML


Les annotations @Entity (et toutes les autres annotations JPA) peuvent tre remplaces ou/et surcharges (les fichiers XML lemportent sur les annotations) par des informations enregistres dans un fichier de configuration XML Exemple :
<table-generator name="empgen" table="ID_GEN" pk-column-value="EmpId"/>

Configuration de la connexion
Il est ncessaire dindiquer au fournisseur de persistance comment il peut se connecter la base de donnes Les informations peuvent tre donnes dans un fichier persistence.xml situ dans un rpertoire META-INF dans le classpath Ce fichier peut aussi comporter dautres informations ; il est tudi en dtails dans la partie 2 du cours sur JPA ; section Configuration dune unit de persistance )
R. Grin JPA page 18

La suite nutilisera essentiellement que les annotations


R. Grin JPA page 17

Exemple (1/3)
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> <persistence-unit name="employes" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.Persi stenceProvider</provider> <class>jpa.Departement</class> <class>jpa.Employe</class>

Exemple (2/3)
<properties> <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/> <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@cl.truc.fr:1521:XE"/>

R. Grin

JPA

page 19

R. Grin

JPA

page 20

Exemple (3/3)
<property name="javax.persistence.jdbc.user" value="toto"/> <property name="javax.persistence.jdbc.password" value="xxxxx"/> </properties> </persistence-unit> </persistence>

Gestionnaire dentits
Classe javax.persistence.EntityManager Le gestionnaire dentits (GE) est linterlocuteur principal pour le dveloppeur Il fournit les mthodes pour grer les entits : les rendre persistantes, les supprimer de la base de donnes, retrouver leurs valeurs dans la base, etc.

R. Grin

JPA

page 21

R. Grin

JPA

page 22

Exemple de code (1)


EntityManagerFactory emf = Persistence. createEntityManagerFactory("employes"); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); Dept dept = new Dept("Direction", "Nice"); em.persist(dept); sera enregistr dans la base de donnes dept.setLieu("Paris"); tx.commit();
R. Grin JPA page 23

Exemple de code (2)


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()
R. Grin JPA page 24

Encadrer par try-catch-finally


Remarque : le code prcdent (et de nombreux exemples de ce cours) devrait tre inclus dans un bloc try finally (les close finaux dans le finally), et pourrait contenir ventuellement des blocs catch pour attraper les exceptions (des RuntimeException) lances par les mthodes de EntityManager Ce bloc try finally a t omis pour ne pas alourdir le code
R. Grin JPA page 25

Exemple avec try-catch-finally


EntityManagerFactory emf = null; EntityManager em = null; EntityTransaction tx = null; try { emf = Persistence.createEntityManagerFactory(".."); em = emf.createEntityManager(); tx = em.getTransaction(); tx.begin(); ... tx.commit(); } catch(Exception e) { if (tx != null) tx.rollback; } finally { if (em != null) em.close(); if (emf != null) emf.close(); }
R. Grin JPA page 26

try avec ressources


Depuis le JDK 7.0, il est possible dutiliser un try avec ressource qui allge le code Une future version de JPA permettra de lutiliser avec les gestionnaires dentits et leur fabrique (pas encore le cas pour la version JPA 2.0)

Exemple de try avec ressources


EntityTransaction tx = null; try ( EntityManagerFactory emf = Persistence.createEntityManagerFactory(".."); EntityManager em = emf.createEntityManager();) { tx = em.getTransaction(); tx.begin(); ... tx.commit(); } catch(Exception e) { if (tx != null) tx.rollback; }

Ce code ne fonctionne pas avec JPA 2.0


R. Grin JPA page 27 R. Grin JPA page 28

Contexte de persistance
La mthode persist(objet) de la classe EntityManager rend persistant un objet Lobjet est ajout un contexte de persistance qui est gr par le GE Toute modification apporte un objet du contexte de persistance sera enregistre dans la base de donnes Lensemble des entits gres par un GE sappelle un contexte de persistance
R. Grin JPA page 29

GE contexte de persistance
Dans le cadre dune application autonome, la relation est simple : un GE possde un contexte de persistance, qui nappartient qu lui et il le garde pendant toute son existence Lorsque le GE est gr par un serveur dapplications, la relation est plus complexe ; un contexte de persistance peut se propager dun GE un autre et il peut tre ferm automatiquement la fin de la transaction en cours (pas tudi dans ce cours)
R. Grin JPA page 30

Caractristiques
Seules les entits peuvent tre n passes en paramtre dune mthode dun EntityManager ou dun Query n renvoyes par une requte (Query) le but dune association rfrences dans une requte JPQL Une classe entit peut utiliser dautres classes pour conserver des tats persistants (MappedSuperclass ou Embeddable tudies plus loin ; depuis JPA 2, les 3 derniers points sont aussi vrais pour les Embeddable)
n n
page 31 R. Grin JPA page 32

Entits

R. Grin

JPA

Conditions pour une classe entit


Elle doit possder un attribut qui reprsente la cl primaire dans la BD (@Id) Une classe entit doit avoir un constructeur sans paramtre protected ou public Elle ne doit pas tre final Aucune mthode ou champ persistant ne doit tre final Si une instance peut tre passe par valeur en paramtre dune mthode comme un objet dtach, elle doit implmenter Serializable
R. Grin JPA page 33

Conditions pour une classe entit


Elle ne doit pas tre une classe interne Elle peut tre une classe abstraite mais elle ne peut pas tre une interface

R. Grin

JPA

page 34

Convention de nommage JavaBean


Un JavaBean possde des proprits Une proprit nomme prop est reprsente par 2 mthodes pour lire et crire sa valeur : n getProp() (ou isProp() si la proprit est de type boolean) (le getter ) n setProp(TypeDeProp prop)(le setter ) Souvent une proprit correspond une variable dinstance de mme nom, mais a nest pas obligatoire
R. Grin JPA page 35

2 types daccs
Ltat persistant dun objet est constitu par les valeurs de ses attributs Le fournisseur de persistance peut accder la valeur dun attribut de 2 faons n soit en accdant directement la variable dinstance ; cest laccs par champ n soit en passant par les accesseurs (getter ou setter) ; cest laccs par proprit

R. Grin

JPA

page 36

Conditions sur les accesseurs


Si laccs se fait par champ, la variable dinstance peut ne pas avoir de getter et de setter Si laccs se fait par proprit, les getter et setter sont tous les deux obligatoires ; ils doivent tre protected ou public

Accs par proprit


Les accesseurs peuvent contenir dautres instructions que le seul code li la valeur de la variable sous-jacente Ces instructions seront excutes par le fournisseur de persistance Si une exception est leve par un accesseur, la transaction est marque pour un rollback ; les exceptions contrles sont enveloppes par une PersistenceException (non contrle, sous RuntimeException)
R. Grin JPA page 38

R. Grin

JPA

page 37

Type daccs par dfaut


Le type daccs par dfaut (par champ ou par attribut) est dfini par la position des annotations dans la classe entit Il doit tre le mme pour toute une hirarchie dhritage (ne pas mlanger les types daccs) JPA 2.0 permet aussi de choisir le type daccs pour chaque classe, et mme pour chaque attribut dans une classe, en ajoutant une annotation Access : @Access(AccessType.PROPERTY) ou @Access(AccessType.FIELD)
R. Grin JPA page 39

Indiquer un autre mode daccs lintrieur dune classe (1/2)


3 tapes pour indiquer un autre mode daccs que laccs par dfaut pour un des attribut dune classe Le transparent suivant donne les 3 tapes pour le cas o la classe a un mode daccs par champ et o on veut un mode daccs par proprit pour un attribut nom Pour le cas inverse, il suffit dinverser les rles des champs et des getters
R. Grin JPA page 40

Indiquer un autre mode daccs lintrieur dune classe (2/2)


1.

@Access(PROPERTY)
Si laccs par dfaut est laccs par champ et quun getter est annot avec @Access(AccessType.PROPERTY), il ne faut pas oublier dannoter le champ correspondant avec @Transient Sinon lattribut sera rendu persistant dans 2 colonnes de la base de donnes

Donner explicitement le mode daccs de la classe par une annotation (ne pas oublier !) : @Entity @Access(AccessType.FIELD) public class Annoter le getter par son mode daccs : @Access(AccessType.PROPERTY) String getNom() { Annoter par @Transient le champ correspondant la proprit : @Transient String nom;
JPA page 41

2.

3.

R. Grin

R. Grin

JPA

page 42

Une erreur ne pas faire


Tous les attributs dune hirarchie de classes qui ne sont pas annots par @Access doivent avoir le mme type daccs Le mlange dannotations sur les variables dinstance et sur les getter peuvent causer des erreurs difficiles comprendre pour un dbutant

Quel type daccs choisir ? (1)


En programmation objet il est conseill dutiliser plutt les accesseurs que les accs directs aux champs (meilleur contrle des valeurs) Pour JPA cest diffrent : laccs par proprit, oblige avoir des setters et getters pour toutes les proprits, ce qui peut tre nfaste et aller lencontre du souci dencapsulation Par exemple, les setters peuvent permettent lutilisateur de ne pas utiliser une mthode ajoute pour obliger bien mettre jour les 2 bouts dune association bidirectionnelle
R. Grin JPA page 44

R. Grin

JPA

page 43

Quel type daccs choisir ? (2)


Laccs par champ permet de distinguer laccs aux attributs par JPA et laccs aux attributs par lapplication (effectu par setters et getters) Il est donc conseill de choisir plutt laccs par champ avec JPA Pour des cas particuliers il est toujours possible dutiliser @Access(PROPERTY) sur certains attributs ; mais attention, un traitement complexe dans un setter peut occasionner un problme sil dpend de la valeur dautres attributs (pas ncessairement initialiss ce moment)
R. Grin JPA page 45

Attributs persistants
Par dfaut, tous les attributs dune entit sont persistants Lannotation @Basic indique quun attribut est persistant mais elle nest donc indispensable que si on veut prciser des informations sur cette persistance (par exemple, une rcupration retarde) Seuls les attributs dont la variable est transient, ou qui sont annots par @Transient, ne sont pas persistants
R. Grin JPA page 46

Types persistants (1)


Les attributs persistants des entits peuvent tre dun des types suivants : n type basic (appel ainsi dans la spcification JPA) n type Embeddable (tudi plus loin dans ce cours) n collection dlments de type basic ou Embeddable (nouveaut de JPA 2)

Types persistants (2)


Un attribut persistant peut aussi reprsenter une association entre entits : n entit n collection dentits Cest le type dclar de lattribut qui dtermine la faon de le rendre persistant par le fournisseur de persistance

R. Grin

JPA

page 47

R. Grin

JPA

page 48

Types basic
Types primitifs (int, double,) String, BigInteger, BigDecimal, classes enveloppes de type primitifs (Integer,) Date (des paquetages util et sql), Calendar, Time, Timestamp Enumrations Tableaux de byte, Byte, char, Character Plus gnralement Serializable (un tel attribut sera sauvegard comme un tout dans la base, dans une seule colonne)
R. Grin JPA page 49

Et les autres tableaux ?


On remarque que les seuls tableaux persistants sont les tableaux de byte et de Character Si une classe a un attribut tableau dun autre type, que va-t-il se passer ? Si le type des lments du tableau est Serializable, le tableau le sera aussi et le tableau sera rendu persistant comme un Serializable, cest--dire comme un tout (Blob ou Clob)
R. Grin JPA page 50

Cycle de vie dune instance dentit


Linstance peut tre n nouvelle (new) : elle est cre mais pas associe un contexte de persistance n gre par un gestionnaire de persistance ; elle a une identit dans la base de donnes (un objet peut devenir gr par la mthode persist, ou merge dune entit dtache ; un objet gr peut aussi provenir dune requte faite par un gestionnaire dentits ou dune navigation partir dun objet gr)
R. Grin JPA page 51

Cycle de vie dune instance dentit


dtache : elle a une identit dans la base mais elle nest plus associe un contexte de persistance (une entit peut, par exemple, devenir dtache si le contexte de persistance est vid ou si elle est envoye dans une autre JVM par RMI) n supprime : elle a une identit dans la base ; elle est associe un contexte de persistance et ce contexte doit la supprimer de la base de donnes (passe dans cet tat par la mthode remove)
n
R. Grin JPA page 52

Cycle de vie dune entit


refresh clear ou detach

Tables de la base de donnes


Dans les cas simples, une table correspond une classe n le nom de la table est le nom de la classe n les noms des colonnes correspondent aux noms des attributs persistants Par exemple, les donnes de la classe Departement sont enregistres dans la table Departement (ou DEPARTEMENT) dont les colonnes se nomment id, nom, lieu
R. Grin JPA page 54

Nouvelle

persist

Gre
merge remove

Dtache

find Query BD

Supprime
R. Grin JPA page 53

Configuration par exception


La configuration des classes entits suppose des valeurs par dfaut pour le mapping de ces classes avec les tables de la base de donnes Il nest ncessaire dajouter des informations de configuration que si ces valeurs par dfaut ne conviennent pas Par exemple, @Entity suppose que la table qui contient les donnes des instances de la classe a le mme nom que lentit
R. Grin JPA page 55

Gnration du schma relationnel


Lorsque la base de donnes est cre par lapplication JPA, les valeurs par dfaut conviennent le plus souvent Voir la section Prcisions pour la gnration du schma de la base de donnes la fin de la partie 2 de ce support

R. Grin

JPA

page 56

Adaptation un schma prexistant


Lorsque le schma de la base de donnes existe dj lorsque lapplication qui utilise JPA est crite, les valeurs par dfaut ne conviennent souvent pas, surtout pour ce qui concerne les associations entre entits Voir la section Adaptation une base relationnelle prexistante vers la fin de la partie 2 de ce support

Nom de table
Pour donner la table un autre nom que le non de la classe, il faut ajouter une annotation @Table Exemple :
@Entity @Table(name = "AUTRE_NOM") public class Classe { ... }

La casse indiffrente pour les noms de table ou de colonne : AUTRE_NOM = autre_Nom


(sauf pour certains SGBD comme MySQL)
R. Grin JPA page 58

R. Grin

JPA

page 57

Nom de colonne
Pour donner une colonne de la table un autre nom que le nom de lattribut correspondant, il faut ajouter une annotation @Column Cette annotation peut aussi comporter des attributs pour dfinir plus prcisment la colonne Exemple :
@Column(name="NOM_CLIENT", updatable=false, length=80) private String nomClient;
R. Grin JPA page 59

Classe Embeddable (1)


Les instances dune classe annote @Embeddable sont persistantes mais elles nont pas une identit dans la base de donnes Des attributs dune entit peuvent tre annots @Embedded pour indiquer que leur type est une classe Embeddable (optionnel ; par dfaut si le type de lattribut est annot par @Embeddable) Les donnes de ces attributs seront sauvegardes dans la table associe lentit qui les contient
R. Grin JPA page 60

10

Exemple
@Embeddable public class Adresse { private int numero; private String rue; private String ville; . . . } @Entity public class Employe { @Embedded private Adresse adresse; ... Optionnel
R. Grin JPA page 61

Classe Embeddable (2)


Elle peut contenir les mmes annotations que les entits (avec @Column par exemple) Elle doit remplir les mmes conditions que les entits (constructeur sans paramtre,) Le type daccs est le mme que lentit (ou mapped superclass ou classe Embeddable) qui la contient (lannotation Access peut tre utilis pour changer ce type daccs)

R. Grin

JPA

page 62

Classe Embeddable (3)


Les types permis pour les attributs sont les mmes que les types permis pour les attributs des entits, y compris les Embeddable ou les collections dEmbeddable Elle peut contenir une association vers une ou plusieurs entits ; lassociation se fera entre lentit qui contient la classe Embeddable et lautre entit

Restriction sur les classes Embeddable


Une instance des ces classes ne peut pas tre rfrence par plusieurs entits diffrentes

R. Grin

JPA

page 63

R. Grin

JPA

page 64

Utilisation multiple dune classe Embeddable


Une classe entit peut rfrencer plusieurs instances dune mme classe Embeddable Par exemple, la classe Employe peut comporter ladresse du domicile et ladresse du travail des employs En ce cas, les noms des colonnes dans la table de lentit ne peuvent tre les mmes pour chacune des utilisations Lannotation @AttributeOverride peut rsoudre le problme
R. Grin JPA page 65

@AttributeOverride(s)
Un champ annot par @Embedded peut tre complt par une annotation @AttributeOverride, ou plusieurs de ces annotations insres dans une annotation @AttributeOverrides Ces annotations permettent dindiquer le nom dune ou de plusieurs colonnes dans la table de lentit Elles peuvent aussi tre utilises si une classe insre est rfrence par plusieurs classes entits diffrentes
R. Grin JPA page 66

11

Exemple
@Entity public class Employe { @Embedded @AttributeOverrides({ @AttributeOverride( name="ville", column=@column(name="ville_travail")), @AttributeOverride(...) }) // Adresse du travail private Adresse adresseTravail;
R. Grin JPA page 67

Annotation pour LOB


Lannotation @Lob permet dindiquer quun attribut est un LOB (Large OBject) : soit un CLOB (Character LOB, tel un long rsum de livre), soit un BLOB (Binary LOB, tel une image ou une squence vido) Le fournisseur de persistance pourra ainsi ventuellement traiter lattribut de faon spciale (utilisation de flots dentres-sorties par exemple) Exemple : @Lob private byte[] image
R. Grin JPA page 68

Mode de rcupration des attributs


Un attribut peut tre rcupr en mode retard : il nest charg en mmoire que si cest ncessaire, cest--dire si le code dsigne explicitement lattribut Par dfaut, tous les attributs dune entit sont chargs en mmoire en mme temps que lentit ; ils sont en mode EAGER

Mode de rcupration des attributs


Si un attribut est dun type de grande dimension (LOB), il peut tre intressant pour les performance ou loccupation mmoire de le passer en mode LAZY :
@Lob @Basic(fetch = FetchType.LAZY) private byte[] cvPdf

R. Grin

JPA

page 69

( utiliser avec parcimonie car peut gnrer un accs supplmentaire la base de donnes et provoquer des problmes si lentit est dtache) Cette annotation nest quune suggestion au GE, quil peut ne pas suivre R. Grin JPA page 70

Annotation pour numration


Une annotation spciale nest pas ncessaire pour un attribut de type numration si lnumration est sauvegarde dans la BD sous la forme des numros des constantes de lnumration (de 0 n) Si on souhaite sauvegarder les constantes sous la forme de la forme dune String qui reprsente le nom de la valeur de lnumration, il faut utiliser lannotation @Enumerated
R. Grin JPA page 71

Exemple
@Enumerated(EnumType.STRING) private TypeEmploye typeEmploye;

R. Grin

JPA

page 72

12

Types temporels
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 une annotation @Temporal Cette indication permettra au fournisseur de persistance de savoir comment dclarer la colonne correspondante dans la base de donnes : une date (un jour), un temps sur 24 heures (heures, minutes, secondes la milliseconde prs) ou un timeStamp (date + heure la microseconde prs)
R. Grin JPA page 73

Annotation pour les types temporels


3 types temporels dans lnumration TemporalType : DATE, TIME, TIMESTAMP Correspondent aux 3 types de SQL ou du paquetage java.sql : Date, Time et Timestamp

R. Grin

JPA

page 74

Exemple
@Temporal(TemporalType.DATE) private Calendar dateEmb;

Collection dlments
JPA 2 a ajout la possibilit de sauvegarder dans une table part les attributs qui sont des collections dlments de type basic ou Embeddable, appeles collection dlments dans la spcification Ces attributs doivent tre annots avec lannotation @ElementCollection Si lannotation nest pas utilise, lattribut est considr comme un Serializable et sauvegard comme un LOB dans la base

R. Grin

JPA

page 75

R. Grin

JPA

page 76

Reprsentation de la collection dans la base de donnes


Les donnes de la collection sont reprsentes dans la BD par une table qui contient la cl primaire de lentit et une ou plusieurs colonnes qui correspondent aux donnes de type basic ou de type embeddable Lannotation @CollectionTable permet de changer la valeur par dfaut du nom de la table (nomEntit_nomAttributCollection) Le nom de la colonne peut tre modifi avec lattribut habituel @Column
R. Grin JPA page 77

Annotation @ElementCollection
Le mode de rcupration des lments de la collection est LAZY par dfaut (voir la section sur les complments sur les associations plus loin dans ce support) Il est possible dindiquer un mode EAGER avec lannotation @ElementCollection

R. Grin

JPA

page 78

13

Exemples
@ElementCollection private Set<String> synonymes = new HashSet<String>(); @ElementCollection(fetch=FetchType.EAGER) private Set<String> synonymes = new HashSet<String>();

Map de types basic ou embeddable


Lannotation @ElementCollection peut aussi tre utilise pour une map dont un des types est basic ou embeddable Comme les collections, les maps sont sauvegardes dans une table part La diffrence est que la table contient une colonne de plus pour les valeurs de la cl de la map @MapKeyColumn permet de changer la valeur par dfaut pour le nom de la colonne
R. Grin JPA page 80

R. Grin

JPA

page 79

Tables multiples
Il est possible de sauvegarder une entit sur plusieurs tables Voir @SecondaryTable dans la spcification JPA Cest surtout utile pour les cas o la base de donnes existe dj et ne correspond pas tout fait au modle objet

Schma relationnel
Dans le cas o le schma relationnel est construit automatiquement partir des annotations, il est possible de prciser des informations sur les tables gnres ou les colonnes de ces tables Par exemple, une contrainte dunicit, ou not null , la longueur des colonnes de type varchar, la prcision des nombres virgule, ou mme le texte entier qui permet de dfinir une colonne (en SQL) Pour plus de dtails voir la fin de la 2me partie de ce cours sur JPA ou la spcification JPA
R. Grin JPA page 82

R. Grin

JPA

page 81

Exemple
@Entity @Table(name="PARTICIPATION2", uniqueConstraints = @UniqueConstraint( columnNames = {"EMPLOYE_ID", "PROJET_ID"}) ) public class Participation { ... }
R. Grin JPA page 83

Les interfaces (1/2)


Une interface ne peut tre une entit Si une classe a une association avec dautres classes, lassociation ne peut donc tre traduite en JPA par un attribut de type interface ou une collection dattributs dont les lments sont des interfaces Par exemple, la classe Dessin ne peut contenir un attribut Collection<Dessinable> pour traduire le fait quun dessin est compos de figures dessinables (Dessinable est une interface)
R. Grin JPA page 84

14

Les interfaces (2/2)


La solution est de sarranger pour avoir une classe mre entit, avec un id, au-dessus de toutes les classes qui implmentent linterface Si une des classes hrite dj dune autre classe, cette solution nest pas possible Il faut alors modifier cette classe et remplacer lhritage par de la composition ; la classe peut ainsi hriter de la classe mre entit qui contient un id

Gestionnaire dentits (Entity Manager), GE

R. Grin

JPA

page 85

R. Grin

JPA

page 86

Principe de base
La persistance des entits nest pas transparente Une instance dentit ne devient persistante que lorsque lapplication appelle la mthode approprie du gestionnaire dentits (persist ou merge) Cette conception a t voulue par les concepteurs de lAPI par souci de flexibilit et pour permettre un contrle fin sur la persistance des entits
R. Grin JPA page 87 R. Grin

Unit de persistance
Cest une configuration nomme qui contient les informations ncessaires lutilisation dune base de donnes Elle est associe un ensemble de classes entits

JPA

page 88

Configuration dune unit de persistance


Les informations sur une unit de persistance sont donnes dans un fichier persistence.xml situ dans un sousrpertoire META-INF dun des rpertoires du classpath Voir section Configuration dune unit de persistance dans la suite du cours

Contexte de persistance (1)


Les entits gres par un gestionnaire dentits forment un contexte de persistance Quand une entit est incluse dans un contexte de persistance (persist ou merge), ltat de lentit est automatiquement sauvegard dans la base au moment du commit de la transaction Proprit importante : dans un contexte de persistance il nexiste pas 2 entits diffrentes qui reprsentent des donnes identiques dans la base
R. Grin JPA page 90

R. Grin

JPA

page 89

15

Contexte de persistance (2)


Un contexte de persistance ne peut appartenir qu une seule unit de persistance Une unit de persistance peut contenir plusieurs contextes de persistance Cest la responsabilit de lapplication de sassurer quune entit nappartient qu un seul contexte de persistance (afin que 2 entits de 2 contextes de persistance diffrents ne puissent correspondre des donnes identiques dans la base de donnes)
R. Grin JPA page 91

Contexte de persistance - cache


Le contexte de persistance joue le rle de cache et vite ainsi des accs la base Si le code veut rcuprer des donnes (par un find ou un query) qui correspondent une entit du contexte, ce sont les donnes du cache qui sont renvoyes Important : si les donnes de la base ont t modifies (et valides) en parallle sans utiliser ce contexte de persistance, les donnes rcupres dans le cache ne tiennent pas compte de ces modifications
R. Grin JPA page 92

Contexte de persistance - cache


Ce fonctionnement peut tre bnfique : meilleures performances, isolation lecture rptable sans modifier les paramtres de la base de donnes Sil pose un problme, il est possible de rcuprer des modifications effectues en parallle sur les donnes dune entit en utilisation la mthode refresh de EntityManager

Interface EntityManager
Elle reprsente un GE Implmentation fournie par le fournisseur de persistance

R. Grin

JPA

page 93

R. Grin

JPA

page 94

Types de GE
GE gr par le container (uniquement disponible dans un serveur dapplications ; pas tudi dans ce cours) ; le contexte de persistance nexiste souvent que le temps dune seule transaction GE gr par lapplication (seul type disponible en dehors dun serveur dapplications) ; le contexte de persistance reste attach au GE pendant toute son existence

Cycle de vie dun GE


En dehors dun serveur dapplications, cest lapplication qui dcide de la dure de vie dun GE La mthode createEntityManager() de la classe EntityManagerFactory cr un GE Le GE est ferm avec la mthode close() de la classe EntityManager ; il ne sera plus possible de lutiliser ensuite
R. Grin JPA page 96

R. Grin

JPA

page 95

16

Fabrique de GE
La classe Persistence permet dobtenir une fabrique de gestionnaire dentits par la mthode createEntityManagerFactory 2 variantes surcharges de cette mthode : n 1 seul paramtre qui donne le nom de lunit de persistance (dfinie dans le fichier persistence.xml) me paramtre de type Map qui contient n Un 2 des valeurs qui vont craser les proprits par dfaut contenues dans persistence.xml
R. Grin JPA page 97

A savoir
Une EntityManagerFactory est threadsafe Un EntityManager ne lest pas Crer une EntityManagerFactory est une opration lourde Crer un EntityManager est une opration lgre Il est donc intressant de conserver une EntityManagerFactory entre 2 utilisations
R. Grin JPA page 98

Interface EntityManagerFactory
Implmente par les fabriques de GE renvoyes par la mthode createEntityManagerFactory Elle contient la mthode isOpen() utilise pour savoir si une fabrique est ouverte et la mthode close() qui doit tre lance lorsque lon na plus besoin de la fabrique, pour librer les ressources quelle utilise La mthode close rend inutilisables tous les GE crs par la fabrique
R. Grin JPA page 99

Mauvaise configuration
Si elle rencontre une mauvaise configuration (dans le fichier persistence.xml, dans les annotations, y compris dans la syntaxe des requtes nommes ou dans les fichiers XML) la mthode createEntityManagerFactory ne se termine pas correctement et lance une exception

R. Grin

JPA

page 100

Mthodes de EntityManager
void persist(Object entit) <T> T merge(T entit) void remove(Object entit) <T> T find(Class<T> classeEntit, Object clPrimaire) <T> T getReference(Class<T> classeEntit, Object clPrimaire) void flush() void setFlushMode(FlushModeType flushMode)
R. Grin JPA page 101

Mthodes de EntityManager
void lock(Object entit, LockModeType lockMode) void refresh(Object entit) void clear() void detach(Object entit) boolean contains(Object entit) void joinTransaction() void close() boolean isOpen()
R. Grin JPA page 102

17

Mthodes de EntityManager
EntityTransaction getTransaction() Query createQuery(String requte) Query createNamedQuery(String nom) Query createNativeQuery(String requte) Query createNativeQuery(String requte, Class classeRsultat)

flush
Toutes les modifications effectues sur les entits du contexte de persistance gres par le GE sont enregistres dans la BD lors dun flush du GE (mais il faudra un commit pour que ces modifications soient dfinitivement enregistres dans la BD) Au moment du flush, le GE tudie ce quil doit faire pour chacune des entits quil gre et il lance les commandes SQL adaptes pour modifier la base de donnes (INSERT, UPDATE ou DELETE)
R. Grin JPA page 104

R. Grin

JPA

page 103

flush
Un flush est automatiquement effectu au moins chaque commit de la transaction en cours Une exception TransactionRequiredException est leve si la mthode flush est lance en dehors dune transaction

flush
Soit X une des entits gre, avec une association de X vers une entit Y Si cette association est note avec cascade=PERSIST ou cascade=ALL, Y est elle aussi flushe Sinon, si Y est new ou removed, une exception IllegalStateException est leve et la transaction est marque pour un rollback Sinon, si Y est dtache et X possde lassociation, Y est flushe ; si Y est le bout propritaire (voir section associations plus loint), le comportement est indfini
R. Grin JPA page 106

R. Grin

JPA

page 105

Mode de flush
Normalement (mode FlushMode.AUTO) un flush des entits concernes par une requte est effectu avant la requte pour que le rsultat tienne compte des modifications effectues en mmoire sur ces entits Il est possible d'viter ce flush avec la mthode 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 requte (voir Query)
R. Grin JPA page 107

persist
Une entit nouvelle devient une entit gre Ltat de lentit sera sauvegard dans la BD au prochain flush ou commit Aucune autre instruction ne sera ncessaire pour que les modifications effectues ensuite sur lentit par lapplication soient enregistres au moment du commit En effet le GE conserve toutes les informations ncessaires sur les entits quil gre
R. Grin JPA page 108

18

persist(A)
Si A est nouvelle, elle devient gre Si A tait dj gre, persist est ignore mais lopration persist cascade sur les entits associes si lassociation a lattribut CascadeType.PERSIST Si A est supprime (a t passe en paramtre remove), elle devient gre Si A est dtache, une IllegalArgumentException est lance (il aurait plutt fallu appeler la mthode merge)
R. Grin JPA page 109

Remarque sur persist


Attention, si on rcupre une entit par un find ou un query et que lon modifie cette entit en lui ajoutant des objets associs, ceux-ci ne seront pas automatiquement persistants, mme sil y un cascade = cascadeType.PERSIST sur lassociation vers ces objets La cascade ne marche que pour la mthode persist !
R. Grin JPA page 110

EntityExistException
persist lance une exception non contrle EntityExistsException si lentit existe dj dans la base de donnes Lexception peut tre lance au moment du persist ou au moment du flush dans la base

remove
Une entit gre devient supprime Les donnes correspondantes seront supprimes de la BD

R. Grin

JPA

page 111

R. Grin

JPA

page 112

remove(A)
Si A est une entit gre, elle devient supprime (les donnes correspondantes de la base seront supprimes de la base au moment du flush du contexte de persistance) Ignor si A est nouvelle ou dj supprime Si A est dtache, une IllegalArgumentException est lance

refresh
Le GE peut synchroniser avec la BD une entit quil gre en rafraichissant son tat en mmoire avec les donnes actuellement dans la BD : em.refresh(entite); Les donnes de la BD sont copies dans lentit Utiliser cette mthode pour sassurer que lentit a les mmes donnes que la BD Peut tre utile pour les transactions longues
R. Grin JPA page 114

R. Grin

JPA

page 113

19

refresh(A)
Ignore si A est nouvelle ou supprime Si A est nouvelle, lopration cascade sur les associations qui ont lattribut CascadeType.REFRESH Si A est dtache, une IllegalArgumentException est lance

clear et detach
clear() vide le contexte de persistance Toutes les entits gres de ce contexte deviennent dtaches detach(entit) enlve lentit du contexte de persistance ; lentit devient dtache ; lance une IllegalArgumentException si largument nest pas une entit gre

R. Grin

JPA

page 115

R. Grin

JPA

page 116

find
La recherche est polymorphe : l'entit rcupre peut tre de la classe passe en paramtre ou d'une sous-classe (renvoie null si aucune entit na lidentificateur pass en paramtre) Exemple :
Article p = em.find(Article.class, 128);

lock(A)
Le fournisseur de persistance gre les accs concurrents aux donnes de la BD reprsentes par les entits avec une stratgie optimiste lock permet de modifier la manire de grer les accs concurrents une entit A Sera tudi plus loin dans la section sur la concurrence

peut renvoyer un article de n'importe quelle sous-classe de Article (Stylo, Ramette,)

R. Grin

JPA

page 117

R. Grin

JPA

page 118

close
Aprs lappel de cette mthode, toutes les autres mthodes de EntityManager lancent une IllegalStateException (sauf isOpen() et getTransaction()) Il est impossible de rouvrir un EntityManager Dans un environnement gr (J2EE), la mthode est inutile puisque cest le serveur dapplications qui se charge de fermer lEntityManager
R. Grin JPA page 119

joinTransaction
Pour les applications gres par un serveur dapplications (donc hors du cadre de ce cours) lorsquun contexte de persistance est gr par lapplication et que le gestionnaire dentits a t cr alors quaucune transaction JTA ntait en cours Synchronise le contexte de persistance avec la transaction pour que le commit de la transaction provoque automatiquement le flush du contexte de persistance dans la base de donnes
R. Grin JPA page 120

20

Entit dtache (1)


Une application distribue sur plusieurs ordinateurs peut utiliser avec profit des entits dtaches Une entit gre par un GE peut tre dtache de son contexte de persistance ; par exemple, si le GE est ferm ou si lentit est transfre sur une autre machine en dehors de la porte du GE

Entit dtache (2)


Une entit dtache peut tre modifie Pour que ces modifications soient enregistres dans la BD, il est ncessaire de rattacher lentit un GE (pas ncessairement celui do elle a t dtache) par la mthode merge

R. Grin

JPA

page 121

R. Grin

JPA

page 122

merge(A)
Renvoie une entit gre A ; plusieurs cas : Si A est une entit dtache, son tat est copi dans une entit gre A qui a la mme identit que A (si A nexiste pas dj, il est cr) Si A est nouvelle, une nouvelle entit gre A' est cr et ltat de A est copi dans A (un id automatique ne sera mis dans A quau commit) Si A est dj gre, merge renvoie A ; en plus merge cascade pour tous les associations avec lattribut CascadeType.MERGE
R. Grin JPA page 123

merge(A)
Si A a t marque supprime par la mthode remove, une IllegalArgumentException est lance

R. Grin

JPA

page 124

merge(A)
Attention, la mthode merge nattache pas A Elle retourne une entit gre qui a la mme identit dans la BD que lentit passe en paramtre, mais a nest pas le mme objet (sauf si A tait dj gre) Aprs un merge, lapplication devra donc, sauf cas exceptionnel, ne plus utiliser lobjet A ; on aura souvent ce type de code : a = em.merge(a); lobjet anciennement point par a ne sera plus rfrenc
R. Grin JPA page 125

merge une erreur ne pas faire


em.merge(a); a.setMachin(truc); em.commit(); La modification de lobjet rfrenc par a ne sera pas enregistre dans la base car cet objet nest pas gr ; il faut utiliser lobjet renvoy par merge : a = em.merge(a); a.setMachin(truc); em.commit();
R. Grin JPA page 126

21

En dehors dune transaction (1)


Les mthodes suivantes (read only) peuvent tre lances en dehors dune transaction : find, getReference, refresh et requtes (query) Les mthodes flush, lock et modifications de masse (executeUpdate) ne peuvent tre lances en dehors dune transaction

En dehors dune transaction (2)


Dans le cadre dune application autonome (avec un GE gr par lapplication, le cas tudi dans ce cours), les mthodes persist, remove, merge peuvent tre excutes en dehors dune transaction ; les modifications sur les objets grs seront enregistres par un flush ds quune transaction sera active

R. Grin

JPA

page 127

R. Grin

JPA

page 128

En dehors dune transaction (3)


Pour les applications dentreprise, les transactions peuvent tre gres par le container (pas tudi dans ce cours) Dans ce cas, lorsque le contexte de persistance est ferm la fin de la transaction (contexte de persistance non tendu , li une transaction), les mthodes persist, remove, merge ne peuvent tre lances que dans le cadre dune transaction (elles ne peuvent avoir un sens que si un contexte de persistance existe)
R. Grin JPA page 129

En dehors dune transaction (4)


Certains SGBD sont mis en mode autocommit lorsque des modifications sont effectues sur des entits gres en dehors dune transaction, ce qui peut poser de srieux problmes (en cas de rollback de la transaction par lapplication, ces modifications ne seront pas invalides) Il est donc conseill de tester le comportement du SGBD

R. Grin

JPA

page 130

Transaction non termine


Il ne faut jamais oublier de terminer une transaction par commit() ou rollback() car, si on le fait pas, le rsultat dpend du fournisseur de persistance et du SGBD

Identit des entits

R. Grin

JPA

page 131

R. Grin

JPA

page 132

22

Cl primaire
Une entit doit avoir un attribut qui correspond la cl primaire dans la table associe La valeur de cet attribut ne doit jamais tre modifie par lapplication ds que lentit correspond une ligne de la base Cet attribut doit tre dfini dans lentit racine dune hirarchie dhritage (uniquement cet endroit dans toute la hirarchie dhritage) Une entit peut avoir une cl primaire composite (pas recommand)
R. Grin JPA page 133

Annotation
Lattribut cl primaire est dsign par lannotation @Id Pour une cl composite on utilise @EmbeddedId ou @IdClass

R. Grin

JPA

page 134

Type de la cl primaire
Le type de la cl primaire (ou des champs dune cl primaire compose) doit tre un des types suivants : n type primitif Java (ne pas utiliser les types numriques non entiers) n classe qui enveloppe un type primitif n java.lang.String n java.util.Date n java.sql.Date
R. Grin JPA page 135

Gnration automatique de cl
Si la cl est de type numrique entier, lannotation @GeneratedValue indique que la cl primaire sera gnre automatiquement par le SGBD Cette annotation peut avoir un attribut strategy qui indique comment la cl sera gnre (il prend ses valeurs dans lnumration GeneratorType) Si la cl est gnre automatiquement, le code Java ne doit pas y faire rfrence ; par exemple dans le constructeur de la classe
R. Grin JPA page 136

Types de gnration
AUTO : le type de gnration est choisi par le fournisseur de persistance, selon le SGBD (squence, table,) ; valeur par dfaut SEQUENCE : utilise une squence est utilise IDENTITY : une colonne de type IDENTITY est utilise TABLE : une table qui contient la prochaine valeur de lidentificateur est utilise On peut aussi prciser le nom de la squence ou de la table avec lattribut generator
R. Grin JPA page 137

Prcisions sur la gnration


Les annotations @SequenceGenerator et @TableGenerator permettent de donner plus de prcisions sur la squence ou la table qui va permettre de gnrer la cl Elles dfinissent des gnrateurs didentificateurs qui pourront tre utiliss dans toute lunit de persistance, et pas seulement dans la classe dans laquelle elles sont
R. Grin JPA page 138

23

Gnrateurs didentificateurs
Les annotations @SequenceGenerator et @TableGenerator peuvent annoter lidentificateur de lentit ou lentit elle-mme qui les utilise, ou mme une autre entit Si le gnrateur ne sert que dans une seule classe, il vaut mieux mettre lannotation avec lannotation @Id de la classe Sinon, une entre dans un des fichiers XML de configuration de JPA, plutt quune annotation, peut tre un bon emplacement
R. Grin JPA page 139 R. Grin

Exemple de gnrateur
@SequenceGenerator( name = "emp_seq", sequence_name = "emp_seq", allocation_size = 10, initialValue = 600)

JPA

page 140

Exemple dutilisation du gnrateur


@Id @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "emp_seq") private long id; Identificateur du gnrateur

Valeur dincrment dune squence


Si une squence utilise par JPA est cre en dehors de JPA, il faut que la valeur de pr-allocation de JPA (gale 50 par dfaut) corresponde la valeur dincrmentation de la squence ; si a nest pas le cas, on aura alors ce type dannotation :
@SequenceGenerator( name="seq3", sequenceName="seq3", initialValue="125, allocationSize="20")

R. Grin

JPA

page 141

R. Grin

JPA

page 142

persist et id automatique
La spcification nimpose rien sur le moment o la valeur de lidentificateur est mise dans lobjet gr La seule assurance est quaprs un flush dans la base de donnes (donc un commit) lidentificateur aura dj reu sa valeur Avec EclipseLink, Oracle et MySQL (et peuttre avec dautres produits), la valeur de lidentificateur est mise ds lappel de persist, sans attendre le commit, mais il est risqu pour la portabilit de lutiliser
R. Grin JPA page 143

Cl composite
Pas recommand, mais une cl primaire peut tre compose de plusieurs colonnes Peut arriver quand la BD existe dj, en particulier quand la classe correspond une table association (association M:N, cas tudi dans la section suivante sur les associations) 2 possibilits : n @IdClass n @EmbeddedId et @Embeddable
R. Grin JPA page 144

24

Classe pour la cl composite


Dans les 2 cas, la cl primaire doit tre reprsente par une classe Java dont les attributs correspondent aux composants de la cl primaire La classe doit tre public, possder un constructeur sans paramtre, tre srialisable et redfinir equals et hashcode (2 instances doivent tre gales si elles ont les mmes valeurs)
R. Grin JPA page 145

@EmbeddedId
La classe cl primaire est annot par @Embeddable La cl primaire est reprsente dans lentit par un seul attribut, du type de la classe embeddable et annot par @EmbeddedId Le type daccs (par champs ou proprits) de la classe embeddable doit tre le mme que celui de lentit dont la cl primaire est dfinie
R. Grin JPA page 146

Exemple avec @EmbeddedId


@Entity public class Employe { @EmbeddedId private EmployePK employePK; ... } @Embeddable public class EmployePK { private String nom; private Date dateNaissance; ... }
R. Grin JPA page 147

@IdClass
@IdClass correspond au cas o la classe entit comprend plusieurs attributs annots par @Id La classe entit est annote par @IdClass qui prend en paramtre le nom de la classe cl primaire La classe cl primaire nest pas annote ; ses attributs ont les mmes noms et mmes types que les attributs annots @Id dans la classe entit
R. Grin JPA page 148

Exemple avec @IdClass


@Entity @IdClass(EmployePK) public class Employe { @Id private String nom; @Id private Date dateNaissance; ... } public class EmployePK { private String nom; private Date dateNaissance; ... }
R. Grin JPA page 149

Quelle solution choisir ?


@IdClass existe pour assurer une compatibilit avec la spcification EJB 2.0 Cest une affaire de got, mais @EmbeddedId est plus simple car on ne rpte pas 2 fois les mmes dfinitions pour les attributs des cls

R. Grin

JPA

page 150

25

Gnralits
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 indiques par une annotation sur lattribut (ou les attributs) correspondant, pour que JPA puisse les grer correctement ; par exemple : @ManyToOne private Departement departement
page 151 R. Grin JPA page 152

Associations

R. Grin

JPA

Reprsentation des associations 1:N et M:N


Elles sont reprsentes par des collections ou maps qui doivent tre dclares par un des types interface suivants (de java.util) : n Collection n Set n List n Map Les variantes gnriques sont conseilles ; par exemple Collection<Employe>
R. Grin JPA page 153 R. Grin

Types utiliser
Le plus souvent Collection sera utilis Set peut tre utile pour liminer les doublons List peut tre utilis pour conserver un ordre mais ncessite quelques prcautions (voir section Complments sur les associations ) Map permet davoir un accs rapide une entit associe par lintermdiaire dune cl

JPA

page 154

Types ne pas utiliser


Le type dclar ne doit pas tre un type concret, tels que HashSet ou ArrayList pour les entits gres (ce qui permet au fournisseur de persistance dutiliser son propre type concret) Il faut videmment initialiser lattribut avec une classe concrte telle que HashSet ou ArrayList (utiliser des types gnriques de prfrence), mais les types de dclaration doivent tre des interfaces
R. Grin JPA page 155

Association bidirectionnelle
Le dveloppeur est responsable de la gestion correcte des 2 bouts de lassociation Par exemple, si un employ change de dpartement, les collections des employs des dpartements concerns doivent tre modifies Un des 2 bouts est dit propritaire de lassociation

R. Grin

JPA

page 156

26

Bout propritaire
Pour les associations autres que M:N ce bout correspond la table qui contient la cl trangre qui traduit lassociation Pour les associations M:N le dveloppeur peut choisir arbitrairement le bout propritaire Lautre bout (non propritaire, appel aussi bout inverse ) est qualifi par lattribut mappedBy qui donne le nom de lattribut dans le bout propritaire qui correspond la mme association
R. Grin JPA page 157

Exemple
Dans la classe Employe :
@ManyToOne private Departement departement;

Dans la classe Departement :


@OneToMany(mappedBy = "departement") private Collection<Employe> employes;

Quel est le bout propritaire ?

R. Grin

JPA

page 158

Valeurs par dfaut


Des valeurs par dfaut sont supposes pour, par exemple, le nom de la colonne cl trangre qui traduit lassociation (DEPARTEMENT_ID pour lexemple du transparent prcdent) Si ces valeurs ne conviennent pas, ajouter des annotations dans le bout propritaire Par exemple, pour indiquer le nom de la colonne cl trangre : @JoinColumn(name="DEPT_ID")
R. Grin JPA page 159

Annotation @JoinColumn
Cette annotation donne le nom de la colonne cl trangre qui reprsente lassociation dans le modle relationnel Elle doit tre mise du ct propritaire (celui qui contient la cl trangre) Sans cette annotation, le nom est dfini par dfaut : <entit_but>_<cl_primaire_entit_but> par exemple, departement_id
R. Grin JPA page 160

Exemple
@ManyToOne @JoinColumn(name="numero_departement") private Departement departement;

Annotation @JoinColumns
Lannotation @JoinColumns permet dindiquer le nom des colonnes qui constituent la cl trangre dans le cas o il y en a plusieurs (si la cl primaire rfrence contient plusieurs colonnes) En ce cas, les annotations @JoinColumn doivent ncessairement comporter un attribut referencedColumnName pour indiquer quelle colonne est rfrence (parmi les colonnes de la cl primaire rfrence)
page 161 R. Grin JPA page 162

R. Grin

JPA

27

Exemple
@JoinColumns({ @JoinColumn(name = "n1", referencedColumnName = "c1"), @JoinColumn(name = "n2", referencedColumnName = "c2") })

Mthode de gestion de lassociation


Pour faciliter la gestion des 2 bouts dune association bidirectionnelle, il est commode dajouter une mthode qui effectue tout le travail

R. Grin

JPA

page 163

R. Grin

JPA

page 164

Exemple
Dans les associations 1-N, le bout 1 peut comporter ce genre de mthode (dans la classe Departement dune association dpartementemploy) :
public void ajouterEmploye(Employe e) { Departement d = e.getDept(); if (d != null) d.employes.remove(e); this.employes.add(e); employe.setDept(this); }

Et si on oublie un des 2 bouts ?


Si les entits sont utilises dans la suite du programme, on va travailler avec des donnes incohrentes Par exemple, un employ est dans la liste des employs du dpartement 10 alors que sa variable dinstance indique quil est dans le dpartement 20 De plus, les donnes peuvent ne pas tre enregistres dans la base au commit
R. Grin JPA page 166

R. Grin

JPA

page 165

Et si on oublie un des 2 bouts ?


Si une association est modifie par le bout propritaire, la modification est enregistre dans la base de donnes Si elle est modifie par le bout non propritaire, elle nest pas enregistre dans la base Exemple : si un employ est ajout la liste des employs dun dpartement sans que le dpartement de lemploy soit modifi, la modification nest pas enregistre dans la base !
R. Grin JPA page 167

Association 1:1
Annotation @OneToOne Reprsente par une cl trangre ajoute dans la table qui correspond au ct propritaire Exemple :
@OneToOne private Adresse adresse;

R. Grin

JPA

page 168

28

Association 1:1 optionnelle


Lannotation @OneToOne est optionnelle ; on peut ne pas la mettre si les valeurs par dfaut conviennent En effet, tout attribut de type entit dans une entit est considr comme reprsentant une association 1:1

Association 1:1 sur les cls


2 classes peuvent tre relies par leur identificateur : 2 entits sont associes si elles ont les mmes cls Lannotation @PrimaryKeyJoinColumn permet dindiquer quil ne faut pas reprsenter lassociation par une cl trangre part Attention, cest au dveloppeur de sassurer que les entits associes ont bien les mmes cls Depuis JPA 2.0 il vaut mieux utiliser les identits drives (tudies avec les associations M:N ; voir exemple du transparent suivant)
R. Grin JPA page 170

R. Grin

JPA

page 169

Exemple
Voici une partie du code dune entit Parking qui est en association 1-1 avec lentit Employe ; la place de parking dun employ a la mme cl primaire que lemploy Avec PrimaryKeyJoinColumn :
@OneToOne @PrimaryKeyJoinColumn private Employe employe;

Associations 1:N et N:1


Annotations @OneToMany et @ManyToOne Reprsente par une cl trangre dans la table qui correspond au ct propritaire (obligatoirement le ct Many ) pour les associations bidirectionnelles Par dfaut un attribut qui est une collection dentits correspond une association 1:N (@OneToMany est optionnel) unidirectionnelle (sinon il faudrait un attribut dannotation mappedBy)
R. Grin JPA page 172

Avec entit drive (le mieux depuis JPA 2.0) :


@Id @OneToOne private Employe employe;
R. Grin JPA page 171

Exemple
class Employe { @ManyToOne private Departement departement ... } class Departement { ... @OneToMany(mappedBy = "departement") private List<Employe> employes(); ... }

Association 1:N unidirectionnelle


Par dfaut, une association unidirectionnelle 1:N est traduite pas une table association Elle nest pas traduite par une cl trangre dans la table du ct N comme cest le cas pour une association bidirectionnelle

R. Grin

JPA

page 173

R. Grin

JPA

page 174

29

1:N unidirectionnelle
public class Dept { ... @OneToMany @JoinTable(name="DEPT_EMP", joinColumns=@JoinColumn(name="DEPT_ID"), inverseJoinColumns= @JoinColumn(name="EMP_ID")) private Collection<Employe> employes; ... }
R. Grin JPA page 175

Cl trangre pour traduire une association 1:N unidirectionnelle


JPA 2.0 permet de se passer dune table association en ajoutant ct de lannotation @OneToMany (celle qui contient la collection) lannotation @JoinColumn qui prcise le nom de la colonne cl trangre dans la table qui correspond au bout N (lautre bout)

R. Grin

JPA

page 176

Association M:N
Traduite par 1 ou 2 collections (suivant directionnalit) dans les classes qui participent lassociation, annotes par @ManyToMany Le dveloppeur peut choisir le ct propritaire dune association M:N bidirectionnelle ; lautre ct comporte lattribut mappedBy Reprsente par une table association dans la base de donnes relationnelle
R. Grin JPA page 177 R. Grin

Exemple
@ManyToMany private Collection<Projet> projets; @ManyToMany(mappedBy = "projets") private Collection<Employe> employes;

JPA

page 178

Association M:N valeurs par dfaut


Les valeurs par dfaut : n le nom de la table association est la concatnation des 2 tables (celle de lentit propritaire en 1er), spares par _ n les noms des colonnes cls trangres sont les concatnations du nom de lattribut qui pointe vers lautre entit , de _ et de la colonne Id de la table rfrence Si les valeurs par dfaut ne conviennent pas, le ct propritaire doit comporter une annotation @JoinTable
R. Grin JPA page 179

@JoinTable
Donne des informations sur la table association qui va reprsenter lassociation Attribut name donne le nom de la table Attribut joinColumns donne les noms des colonnes de la table qui rfrencent les cls primaires du ct propritaire de lassociation Attribut inverseJoinColumns donne les noms des colonnes de la table qui rfrencent les cls primaires du ct qui nest pas propritaire de lassociation
R. Grin JPA page 180

30

Exemple (classe Employe)


@ManyToMany @JoinTable( name = "EMP_PROJET", joinColumns = @JoinColumn(name = "matr"), inverseJoinColumns = @JoinColumn(name = "code_Projet") ) private Collection<Projet> projets();

Association M:N avec information porte par lassociation


Une association M:N peut porter une information Exemple : Association entre les employs et les projets ; un employ a une (et une seule) fonction dans chaque projet auquel il participe En ce cas, il nest pas possible de traduire lassociation en ajoutant 2 collections (ou maps) comme il vient dtre dcrit
R. Grin JPA page 182

R. Grin

JPA

page 181

Classe association
Lassociation M:N est traduite par une classe association qui a 2 liens annots @ManyToOne vers les classes qui participent lassociation Selon la directionnalit de lassociation, ces classes peuvent aussi contenir chacune une collection de la classe association, annote par @OneToMany

2 cas
2 possibilits pour cette classe, suivant quelle contient ou non un attribut identificateur (@Id) unique Le plus simple est de navoir quun seul attribut identificateur

R. Grin

JPA

page 183

R. Grin

JPA

page 184

Exemple avec 1 attribut identificateur


Association entre les employs et les projets Cas dun identificateur unique : la classe association contient les attributs id (int), employe (Employe), projet (Projet) et fonction (String) Lattribut id est annot par @Id Les attributs employe et projet sont annots par @ManyToOne

Code classe association (dbut)


@Entity public class Participation { @Id @GeneratedValue private int id; @ManyToOne private Employe employe; @ManyToOne private Projet projet; private String fonction;

R. Grin

JPA

page 185

R. Grin

JPA

page 186

31

Code classe association (suite)


public Participation() { } public Participation(Employe employe, Projet projet, String fonction) { this.employe = employe; this.projet = projet; this.fonction = fonction; }

Code classe association (fin)


public Employe getEmploye() { return employe; } public Projet getProjet() { return projet; } }

R. Grin

JPA

page 187

R. Grin

JPA

page 188

Code classe association (complment)


Si le schma relationnel est gnr daprs les informations de mapping par les outils associs au fournisseur de persistance, 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 mme projet :
@Entity @Table(uniqueConstraints = @UniqueConstraint(columnNames = { "EMPLOYE_ID","PROJET_ID" }) public class Participation {

Exemple avec 2 identificateurs


Si la base de donnes existe dj, il est frquent de devoir s'adapter une table association qui contient les colonnes suivantes (pas de colonne id): n employe_id, cl trangre vers EMPLOYE n projet_id, cl trangre vers PROJET
n fonction et qui a (employe_id, projet_id) comme cl primaire En ce cas, la solution est plus complexe

R. Grin

JPA

page 189

R. Grin

JPA

page 190

Difficult avec 2 identificateurs


La difficult vient de lcriture de la classe Participation En effet, a ne marcherait pas dannoter comme composants de la cl, les 2 attributs employe et projet Leur type sont des entits et ne correspondent pas aux entiers qui constituent la cl primaire de la table PARTICIPATION de la BD

Identit drive
JPA 2 prend en compte cette situation avec la notion didentit drive (JPA 1 avait une solution plus complexe et moins portable) Il existe plusieurs variantes qui sont dcrites en dtails dans la spcification de JPA 2 (section 2.4.1.2), selon que les classes qui participent lassociation ont des cls simples ou composes de plusieurs attributs et selon lutilisation de IdClass ou EmbeddedId Pour notre exemple, nous ne verrons ici que la variante avec Embeddedid

R. Grin

JPA

page 191

R. Grin

JPA

page 192

32

Classes Employe et Projet


@Entity public class Employe { @Id private id; @OneToMany(mappedBy="employe") private Collection<Participation> participations; . . . } @Entity public class Projet { @Id private int id; @OneToMany(mappedBy="projet") private Collection<Participation> participations; . . . }
R. Grin JPA page 193

Classe Participation (2 choix pour lidentificateur)


On peut utiliser une classe Embeddable ou une IdClass pour reprsenter la cl composite de Participation Le code suivant utilise une classe Embeddable comme type de lidentificateur @MapsId sur un attribut de lidentificateur qui participe une association, indique la correspondance entre lattribut et le champ de la classe Embeddable
R. Grin JPA page 194

Classe Participation
@Entity public class Participation { @EmbeddedId private ParticipationId id; @MapsId("employePK") @ManyToOne private Employe employe; @MapsId("projetPK") @ManyToOne private Projet projet; private String fonction; ... }
R. Grin JPA page 195

Classe Embeddable des identificateurs


@Embeddable public class ParticipationId { type de lidentificateur private int employePK; de lentit Projet private int projetPK; // Redfinition de equals et hashcode ... // Reste ventuel de la classe ... }

R. Grin

JPA

page 196

Grer les 2 bouts de lassociation


Il faut viter la possibilit quun bout seulement dune association soit gre Pour cela on ajoute souvent une mthode dans une des classes participante, qui gre les 2 bouts de lassociation Dans ce cas particulier, cest le constructeur de Participation qui gre lassociation

Participation (constructeurs)
public Participation() { } // Pour JPA public Participation(Employe employe, Projet projet, String fonction) { this.employe = employe; this.projet = projet; employe.getParticipations.add(this); projet.getParticipations.add(this); this.fonction = fonction; }
R. Grin JPA page 198

R. Grin

JPA

page 197

33

Map pour association


A la place dune collection il est possible dutiliser une map pour les associations OneToMany ou ManyToMany Les valeurs de la map correspondent aux entits associes Important : la classe de la cl doit avoir sa mthode hashCode compatible avec sa mthode equals

Map pour association


Lassociation peut tre annote avec @MapKey qui indique que la cl de la map est lidentificateur de lentit associe (de la classe cl primaire si lentit a une cl primaire composite) La cl de la map peut aussi tre un autre attribut de lentit associe, de type basic, Embedded ou Entity ; en ce cas il faut indiquer le nom de lattribut avec lattribut name de lannotation : @MapKey(name="nom")
R. Grin JPA page 200

R. Grin

JPA

page 199

Map pour association


Attention lannotation @MapKey est obligatoire mme si la valeur de lattribut name est la valeur par dfaut En effet, si on ne met pas cette annotation, JPA considrera que la cl de la map est une valeur supplmentaire et il lassociera une colonne autre que lidentificateur de lentit associe, dans la base de donnes

Exemple
Les employs dun dpartement peuvent tre enregistrs dans une map dont les cls sont les noms des employs (on suppose que 2 employs nont pas le mme nom)
public class Departement { ... @OneToMany(mappedBy = "departement") @MapKey(name = "nom") public Map<String,Employe> getEmployes(){ ... }
R. Grin JPA page 202

R. Grin

JPA

page 201

Autre exemple
La cl doit identifier la valeur dans le contexte de linstance de la classe qui contient la map Les numros de tlphone dun employ sont rangs dans une map dont la cl est le type du numro (mobile, domicile, fixe travail,...)
public class Employe { @OneToMany @MapKeyColumn(name="TYPE_NUMERO") private Map<String,Telephone> tels; ... tels.put("domicile", "0492....");
R. Grin JPA page 203 R. Grin

Complments sur les associations


persistance des entits associes attribut cascade rcupration des entits associes suppression des orphelins ordre des lments dune liste association bidirectionnelle avec un Embeddable
JPA page 204

34

Persistance par transitivit


Un service de persistance implmente la persistance par transitivit (reachability) si une instance devient automatiquement persistante lorsquelle est rfrence par une instance dj persistante Cest un comportement logique : un objet nest pas vraiment persistant si une partie des valeurs de ses proprits nest pas persistante
R. Grin JPA page 205

Pas si simple
Maintenir une cohrence automatique des valeurs persistantes nest pas si simple Par exemple, si un objet devient non persistant, faut-il aussi rendre non persistants tous les objets quil a rendu persistants par transitivit ? De plus, le service de persistance doit alors examiner toutes les rfrences des objets qui sont rendus persistants, et ce, de faon rcursive, ce qui peut nuire aux performances
R. Grin JPA page 206

Le choix de JPA
Par dfaut, JPA neffectue pas de persistance par transitivit automatique : rendre persistant un objet ne suffit pas rendre automatiquement et immdiatement persistants tous les objets quil rfrence Comme la cohrence nest pas gre automatiquement, cest le code de lapplication qui se doit de conserver cette cohrence, au moins au moment du commit
R. Grin JPA page 207

Cohrence des donnes


Si le code a mal gr cette cohrence, une exception est lance Par exemple, si un dpartement est rendu persistant alors que la collection des employs du dpartement contient des employs non grs par le contexte de persistance, une IllegalStateException va tre lance au moment du commit, et la transaction va sans doute tre invalide (rollback) dans un bloc catch(IllegalStateException)
R. Grin JPA page 208

Persistance automatique
Afin de faciliter le maintien de cette cohrence, il est possible dindiquer JPA que les objets associs un objet persistant doivent tre automatiquement rendus persistants Pour cela il suffit dajouter un attribut cascade dans les informations de mapping de lassociation

Attribut cascade
Les annotations qui dcrivent les associations entre objets peuvent avoir un attribut cascade pour indiquer que certaines oprations du GE doivent tre appliques aux objets associs Ces oprations sont PERSIST, REMOVE, REFRESH, DETACH et MERGE ; ALL correspond toutes ces oprations Par dfaut, aucune opration nest applique transitivement
R. Grin JPA page 210

R. Grin

JPA

page 209

35

Exemples
@OneToMany( cascade = CascadeType.PERSIST) private Collection<Employe> employes; @OneToMany( cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy = "client") private Collection<Facture> factures;

Rcupration des entits associes


Lorsquune entit est rcupre depuis la base de donnes par une requte (Query) ou par un find, est-ce que les entits associes doivent tre elles aussi rcupres ? Si elles sont rcupres, est-ce que les entits associes ces entits doivent elles aussi tre rcupres ? On voit que le risque est de rcuprer un trs grand nombre dentits qui ne seront pas utiles pour le traitement en cours
R. Grin JPA page 212

R. Grin

JPA

page 211

EAGER ou LAZY
JPA laisse le choix de rcuprer ou non immdiatement les entits associes, suivant les circonstances Il suffit de choisir le mode de rcupration de lassociation (LAZY ou EAGER) Une requte sera la mme, quel que soit le mode de rcupration Dans le mode LAZY les donnes associes ne sont rcupres que lorsque cest vraiment ncessaire
R. Grin JPA page 213

Rcupration retarde (LAZY)


Dans le cas o une entit associe nest pas rcupre immdiatement, JPA remplace lentit par un proxy , objet qui permettra de rcuprer lentit plus tard si besoin est Ce proxy contient la cl primaire qui correspond lentit non immdiatement rcupre Il est possible de lancer une requte avec une rcupration immdiate, mme si une association est en mode LAZY (join fetch de JPQL tudi plus loin)
R. Grin JPA page 214

Comportement par dfaut de JPA


Par dfaut, JPA ne rcupre immdiatement que les entits associes par des associations dont le but est One (une seule entit lautre bout) : OneToOne et ManyToOne (mode EAGER) Pour les associations dont le but est Many (une collection lautre bout), OneToMany et ManyToMany, par dfaut, les entits associes ne sont pas rcupres immdiatement (mode LAZY)
R. Grin JPA page 215

Indiquer le type de rcupration des entits associes


Lattribut fetch dune association permet dindiquer une rcupration immdiate des entits associes (FetchType.EAGER) ou une rcupration retarde (FetchType.LAZY) si le comportement par dfaut ne convient pas Exemple :
@OneToMany(mappedBy = "departement", fetch = FetchType.EAGER) private Collection<Employe> employes;

R. Grin

JPA

page 216

36

Suppression des orphelins


Certaines entits ne peuvent exister quen association avec dautres entits Par exemple des lignes de commandes ne peuvent exister sans leur commande Pour ces cas, JPA 2 a ajout la possibilit de suppression automatique des orphelins ds quils sont enlevs de la collection qui les contient : ds quune ligne de commande est enleve de la collection contenue dans la commande, elle est supprime (dans la BD)
R. Grin JPA page 217

Attribut orphanRemoval
Si une annotation @OneToMany a lattribut orphanRemoval "true", les entits supprimes de la collection se verront appliquer lopration remove par le gestionnaire dentit (les donnes correspondantes seront supprimes de la BD) Lannotation @OneToOne peut aussi avoir cet attribut ; la suppression de lorphelin a lieu lorsque la rfrence vers lui est mise null dans lentit qui lui est associe
R. Grin JPA page 218

Attribut orphanRemoval
La suppression a lieu au moment du flush Lattribut orphanRemoval implique cascade=REMOVE

Exemple
@Entity public class Facture { ... @OneToMany(mappedBy="facture", cascade=ALL, orphanRemoval= "true") private Collection<LigneFacture> lignes; ... }

R. Grin

JPA

page 219

R. Grin

JPA

page 220

Ordre dans les listes


Par dfaut, lordre dune liste Java nest pas ncessairement prserv dans la base de donnes De plus, lordre en mmoire doit tre maintenu par le code (pas automatique)

Annotations pour lordre dans les listes


Lannotation @OrderBy impose un ordre pour rcuprer les entits associes dans la liste lors dune requte (mais cet ordre nest pas dans la base de donnes ; cest seulement au moment de la rcupration que les donnes sont ordonnes) Depuis JPA 2.0, lannotation @OrderColumn fait maintenir lordre de la liste dans la base de donnes (en ajoutant une colonne dans la base)
R. Grin JPA page 222

R. Grin

JPA

page 221

37

@OrderBy
Il faut prciser un ou plusieurs attributs (spars par une virgule) de type basic, qui dterminent lordre Chaque attribut peut tre prcis par ASC ou DESC (ordre ascendant ou descendant) ; ASC par dfaut Si aucun attribut nest prcis, lordre sera celui de la cl primaire (si la collection correspond une association entre entits) ou lordre de la valeur pour les collections dlments de type basic
R. Grin JPA page 223

Exemples
@Entity public class Departement { ... @OneToMany(mappedBy = "departement") @OrderBy("nomEmploye") private List<Employe> employes;

@OrderBy("poste DESC, nomEmploye ASC")

R. Grin

JPA

page 224

Cas des embeddables


Si la colonne qui sert ordonner appartient un embeddable, la notation pointe peut tre utilise pour la dsigner :
@OrderBy("adresse.codePostal")

@OrderColumn
Cette annotation introduite par JPA 2.0 indique quune colonne dans la BD correspond lordre dune liste Java Cette annotation peut tre ajoute aux associations OneToMany, ManyToMany et aux collections dlments Lannotation doit tre mise du ct de lattribut qui rfrence la liste ordonne ; attention, pour une association 1-N cest donc le ct non propritaire
R. Grin JPA page 226

R. Grin

JPA

page 225

Colonne pour ordonner


La colonne est dans la table association (sil y en a une) ou dans la table qui contient la cl trangre ou dans la table des lments pour une collection dlments Les valeurs de la colonne sont des nombres entiers ; ils commencent 0 et sont contigus (ce qui peut nuire aux performances cause des insertions-suppressions en milieu de liste) Lattribut name de lannotation peut servir donner le nom de la colonne (par dfaut, <nom attribut>_order)
R. Grin JPA page 227

Colonne uniquement dans la BD


La colonne ajoute nest pas visible dans le modle objet (aucun attribut qui lui correspond dans les classes Java) Si lordre dpend des valeurs dune colonne visible dans le modle objet, il faut plutt utiliser @OrderBy vu prcdemment

R. Grin

JPA

page 228

38

Utilisation dans les requtes


Cette colonne sert aussi imposer un ordre lors de la rcupration par une requte (pas besoin dannotation @OrderBy) La fonction INDEX peut tre utilise pour dsigner la valeur de la colonne qui conserve lordre (voir section sur les requtes dans la 2me partie de ce support sur JPA)

Exemple
@Entity public class Facture { ... @OneToMany(mappedBy = "facture") @OrderColumn(name = "numero_ligne") private List<LigneCommande> lignes; ... }

R. Grin

JPA

page 229

R. Grin

JPA

page 230

Association bidirectionnelle avec les classes Embeddable


Soit une association bidirectionnelle entre une entit E1 et une classe Embeddable Emb qui est insre dans une entit E2 Dans lentit E1, il faut dsigner lentit E2 et dans la classe Embeddable il faut dsigner lentit E1

Exemple dassociation dans Embeddable


@Entity class Employe { private Embedded Contact contact; @Embeddable class Contact { @OneToMany(mappedBy="employe") private Set<Telephone> telephones; @Entity class Telephone { @ManyToOne private Employe employe; Pas Contact !

R. Grin

JPA

page 231

R. Grin

JPA

page 232

Stratgies
A ce jour, les implmentations de JPA doivent obligatoirement offrir 2 stratgies pour la traduction de lhritage : n une seule table pour une hirarchie dhritage (SINGLE_TABLE)
n

Hritage

une table par classe ; les tables sont jointes pour reconstituer les donnes (JOINED)

La stratgie une table distincte par classe concrte est seulement optionnelle (TABLE_PER_CLASS)
R. Grin JPA page 233 R. Grin JPA page 234

39

Annotation @Inheritance
Le choix de la stratgie se fait avec lannotation @Inheritance Cest la classe racine de la hirarchie dhritage qui doit tre annote Si on choisit la stratgie par dfaut (SINGLE_TABLE), lannotation est optionnelle : si la classe racine est une entit (annote @Entity) et na pas dannotation @Inheritance, la stratgie dhritage est suppose tre SINGLE_TABLE
R. Grin JPA page 235

Une table par hirarchie


Sans doute la stratgie la plus utilise Valeur par dfaut de la stratgie de traduction de lhritage Performante et permet le polymorphisme Mais beaucoup de valeurs NULL dans les colonnes si la hirarchie est complexe De plus, lajout dun nouveau type dentit aprs le dmarrage de lapplication oblige modifier la dfinition de la table qui contient les donnes
R. Grin JPA page 236

Exemple
Dans la classe @Entity racine de la hirarchie ; @Inheritance(strategy= optionnel InheritanceType.SINGLE_TABLE) public abstract class Personne {...} @Entity Employe par dfaut @DiscriminatorValue("E") public class Employe extends Personne { ... }
R. Grin JPA page 237 R. Grin

Nom de la table
Si on choisit la stratgie une seule table pour une arborescence dhritage la table a le nom de la table associe la classe racine de la hirarchie

JPA

page 238

Colonne discriminatrice (1)


Une colonne de la table doit permettre de diffrencier les lignes des diffrentes classes de la hirarchie dhritage Cette colonne est indispensable pour le bon fonctionnement des requtes qui se limitent une sous-classe Par dfaut, cette colonne se nomme DTYPE et elle est de type Discriminator.STRING de longueur 31 (autres possibilits pour le type : CHAR et INTEGER)
R. Grin JPA page 239

Colonne discriminatrice (2)


Lannotation @DicriminatorColumn permet de modifier les valeurs par dfaut Ses attributs : n name n discriminatorType n columnDefinition fragment SQL pour crer la colonne n length longueur dans le cas o le type est STRING (31 par dfaut)
R. Grin JPA page 240

40

Exemple
@Entity @Inheritance @DiscriminatorColumn( name="TRUC", discriminatorType="STRING", length=5) public class Machin { }

Valeur discriminatrice
Chaque classe est diffrencie par une valeur de la colonne discriminatrice Cette valeur est passe en paramtre de lannotation @DiscriminatorValue Par dfaut cette valeur est le nom de lentit (le nom de la classe si pas dattribut name pour @Entity)

R. Grin

JPA

page 241

R. Grin

JPA

page 242

Une table par classe (1)


Toutes les classes, mme les classes abstraites, sont reprsentes par une table Ncessite des jointures pour retrouver les proprits dune instance dune classe Toutes les tables qui correspondent aux sous-classes ont une cl trangre qui rfrence la cl primaire de la table qui correspond la racine de la hirarchie (voir cours sur le mapping objet-relationnel)

Une table par classe (2)


La table qui correspond la classe racine de la hirarchie dhritage doit comporter une colonne discriminatrice Cette colonne permet de simplifier certaines requtes ; par exemple, pour retrouver les noms de tous les employs (classe Employe qui hrite de la classe Personne la racine de la hirarchie dhritage) Voir la colonne discriminatrice de la stratgie une seule table par hirarchie ; mme valeur par dfaut
R. Grin JPA page 244

R. Grin

JPA

page 243

Exemple
@Entity @Inheritance(strategy= InheritanceType.JOINED) @DiscriminatorValue("P") public abstract class Personne {...} @Entity @DiscriminatorValue("E") public class Employe extends Personne { ... }
R. Grin JPA page 245

@PrimaryKeyJoinColumn
Par dfaut, la colonne cl trangre a le mme nom que la colonne cl primaire rfrence Si a nest pas le cas, il faut utiliser lannotation @PrimaryKeyJoinColumn( name=<nom colonne cl trangre>) Une annotation @PrimaryKeyJoinColumns peut tre utilise en cas de cl trangre compose de plusieurs colonnes

R. Grin

JPA

page 246

41

Une table par classe concrte


Stratgie seulement optionnelle Pas recommand car le polymorphisme est plus complexe obtenir (voir cours sur le mapping objet-relationnel) Performante car chaque classe concrte correspond une seule table totalement spare des autres tables ; toutes les proprits de la classe, mme celles qui sont hrites, se retrouvent dans la table
R. Grin JPA page 247

Exemple
@Entity @Inheritance(strategy= InheritanceType.TABLE_PER_CLASS) public abstract class Personne {...} @Entity @Table(name=EMPLOYE) public class Employe extends Personne { ... }

R. Grin

JPA

page 248

Entit abstraite
Une classe abstraite peut tre une entit (annote par @Entity) Son tat sera persistant et sera utilis par les sous-classes entits Comme toute entit, elle pourra dsigner le type retour dune requte (query) pour une requte polymorphe

Complments
Lannotation @Entity ne shrite pas Les sous-classes entits dune entit doivent tre annote par @Entity Une entit peut avoir une classe mre qui nest pas une entit ; en ce cas, ltat de cette classe mre ne sera pas persistant

R. Grin

JPA

page 249

R. Grin

JPA

page 250

Classe mre persistante


Une entit peut aussi avoir une classe mre dont ltat est persistant, sans que cette classe mre ne soit une entit En ce cas, la classe mre doit tre annote par @MappedSuperclass Aucune table ne correspondra cette classe mre dans la base de donnes ; ltat de cette classe mre sera rendu persistant dans les tables associes ses classes entits filles
R. Grin JPA page 251

Classe mre persistante


Cette classe mre nest pas une entit Donc elle ne pourra pas tre renvoye par une requte, ne pourra pas tre passe en paramtre dune mthode dun EntityManager ou dun Query et ne pourra tre le but dune association

R. Grin

JPA

page 252

42

Exemple
Si toutes les entits ont des attributs pour enregistrer la date de la dernire modification et le nom de lutilisateur qui a effectu cette modification, il peut tre intressant davoir une classe abstraite Base, mre de toutes les entits qui contient ces attributs Cette classe mre sera annote avec @MappedSuperclass

Code de lexemple
@MappedSuperclass public abstract class Base { @Id @GeneratedValue private Long Id; @Version private Integer version; @ManyToOne private User user; @Temporal(value = TemporalType.TIMESTAMP) private Date dateModif; ... }
R. Grin JPA page 254

R. Grin

JPA

page 253

Classe mre non persistante


Une classe entit peut aussi hriter dune classe mre dont ltat nest pas persistant En ce cas, ltat hrit de la classe mre ne sera pas persistant La classe mre ne comportera aucune annotation particulire lie la persistance, ni @Entity, ni @MappedSuperclass

R. Grin

JPA

page 255

43

Vous aimerez peut-être aussi