Vous êtes sur la page 1sur 57

Plan de cette partie

‰ Présentation de JPA
JPA ‰ Entités persistantes

(Java Persistence API)


‰ Gestionnaire de persistance
‰ Compléments sur les entités : identité,
associations, héritage
‰ Langage d’interrogation
Université de Nice - Sophia Antipolis
Version 1.1 – 27/1/07 ‰ Modifications en volume

Richard Grin ‰ Exceptions


‰ Configuration
R. Grin JPA page 2

Plan de cette partie


‰ Transaction
‰ Concurrence
‰ Entités détachées
‰ Optimisation
Présentation de JPA
‰ Callbacks
‰ Fichiers de configuration XML
‰ JPA dans les serveurs d’applications

R. Grin JPA page 3 R. Grin JPA page 4

EJB 3.0 JPA


‰ Java EE 5 (Enterprise Edition) est une plate- ‰ JPA (Java persistence API) est la partie de la
forme de développement et un ensemble de spécification EJB 3.0 qui concerne la persistance
spécifications pour le développement des composants
d’applications d’entreprises multi-tiers ‰ N’effectue la persistance que dans une base de
‰ EJB 3.0 fait partie de Java EE 5 ; c’est une données relationnelle (JDO permet le choix
spécification récente (mai 2006) d’un cadre d’autres types de SGBD)
(framework) pour l’utilisation de composants ‰ Peut s’appliquer sur toutes les applications Java,
métier réutilisables par des serveurs d’application même celles qui s’exécutent en dehors d’un
Java serveur d’application
‰ Utilisation importante des annotations

R. Grin JPA page 5 R. Grin JPA page 6

1
JPA Avertissement
‰ JPA va sans doute devenir un standard pour la ‰ JPA est le plus souvent utilisé dans le
persistance des objets Java contexte d’un serveur d’application
‰ Pour plus de précisions, lire la spécification à ‰ Ce cours étudie l’utilisation de JPA par une
l’adresse application autonome, en dehors de tout
http://jcp.org/aboutJava/communityprocess/pfd/js serveur d’application
r220/index.html ‰ Des informations sur l’utilisation de JPA avec
un serveur d’applications sont données à la
fin de ce support

R. Grin JPA page 7 R. Grin JPA page 8

Fournisseur de persistance Entités


‰ Comme pour JDBC, l’utilisation de JPA ‰ Les classes dont les instances peuvent être
nécessite un fournisseur de persistance qui persistantes sont appelées des entités dans la
implémente les classes et méthodes de l’API spécification de JPA
‰ GlassFish, est l’implémentation de référence ‰ Le développeur indique qu’une classe est une
de la spécification EJB 3 entité en lui associant l’annotation @Entity
‰ GlassFish utilise TopLink essentials comme ‰ Ne pas oublier d’importer
fournisseur de persistance pour JPA javax.Persistence.Entity dans les
classes entités (idem pour toutes les
‰ D’autres implémentations : TopLink,
annotations)
Hibernate Entity Manager, BEA Kodo

R. Grin JPA page 9 R. Grin JPA page 10

Vocabulaire Exemple d’entité – les champs


‰ Dans la suite de ce cours et quand il n’y aura @Entity
pas ambiguïté, « entité » désignera soit une public class Departement {
classe entité, soit une instance de classe private int id;
entité, suivant le contexte private String nom;
private String lieu;
private Collection<Employe> employes =
new List<Employe>();

R. Grin JPA page 11 R. Grin JPA page 12

2
Exemple d’entité – l’identificateur Exemple d’entité – une propriété
@Id
@GeneratedValue public String getNom() {
public int getId() { return nom;
return id; }
} public void setNom(String nom) {
public void setId(int id) { this.nom = nom;
this.id = id; }
}

R. Grin JPA page 13 R. Grin JPA page 14

Exemple d’entité – une association Fichiers de configuration XML


L’association inverse
dans la classe Employe ‰ Les annotations @Entity (et toutes les autres
@OneToMany(mappedBy="dept")
public Collection<Employe> getEmployes() {
annotations JPA) peuvent être remplacées ou/et
return employes;
surchargées (les fichiers XML l’emportent sur les
annotations) par des informations enregistrées
}
dans un fichier de configuration XML
public void setEmployes(Collection<Employe>
emps) { ‰ Exemple :
this.employes = emps; <table-generator name="empgen"
table="ID_GEN" pk-column-value="EmpId"/>
}
} ‰ La suite n’utilisera que les annotations

R. Grin JPA page 15 R. Grin JPA page 16

Gestionnaire d’entités Contexte de persistance


‰ Classe ‰ La méthode persist(objet) de la classe
javax.persistence.EntityManager EntityManager rend persistant un objet
‰ Le gestionnaire d’entités (GE) est ‰ L’objet est alors géré par le GE : toute
l’interlocuteur principal pour le développeur modification apportée à l’objet sera enregistrée
‰ Il fournit les méthodes pour gérer les entités : dans la base de données par le GE
les rendre persistantes, les supprimer de la ‰ L’ensemble des entités gérées par un GE
base de données, retrouver leurs valeurs s’appelle un contexte de persistance
dans la base, etc.

R. Grin JPA page 17 R. Grin JPA page 18

3
Exemple Exemple (suite)
String queryString =
EntityManagerFactory emf = Persistence.
"SELECT e FROM Employe e "
createEntityManagerFactory("employes"); + " WHERE e.poste = :poste";
EntityManager em = Query query = em.createQuery(queryString);
emf.createEntityManager(); query.setParameter("poste", "INGENIEUR");
EntityTransaction tx = em.getTransaction(); List<Employe> liste =
tx.begin(); query.getResultList();
Dept dept = new Dept("Direction", "Nice"); for (Employe e : liste) {
em.persist(dept); System.out.println(e.getNom());
sera enregistré dans
dept.setLieu("Paris"); la base de données }
em.close();
tx.commit();
…au moment du emf.close()
R. Grin commit
JPA page 19 R. Grin JPA page 20

Caractéristiques
‰ Seules les entités peuvent être
n renvoyées par une requête (Query)

n passées en paramètre d’une méthode d’un

Entités EntityManager ou d’un Query


n le but d’une association

n référencées dans une requête JPQL

‰ Une classe entité peut utiliser d’autres classes


pour conserver des états persistants
(MappedSuperclass ou Embedded étudiées
plus loin)
R. Grin JPA page 21 R. Grin JPA page 22

Conditions pour les classes entités Conditions pour les classes entités
‰ Une classe entité doit avoir un constructeur ‰ Une classe entité ne doit pas être une classe
sans paramètre protected ou public interne
‰ Elle ne doit pas être final ‰ Une entité peut être une classe abstraite mais
‰ Aucune méthode ou champ persistant ne doit elle ne peut être une interface
être final
‰ Si une instance peut être passée par valeur en
paramètre d’une méthode comme un objet
détaché, elle doit implémenter Serializable
‰ Elle doit posséder un attribut qui représente la
clé primaire dans la BD
R. Grin JPA page 23 R. Grin JPA page 24

4
Convention de nommage JavaBean 2 types d’accès
‰ Un JavaBean possède des propriétés ‰ Le fournisseur de persistance accédera à la
‰ Une propriété est représentée par 2 valeur d’une variable d’instance
accesseurs (« getter » et « setter ») qui n soit en accédant directement à la variable

doivent suivre la convention de nommage d’instance (par introspection)


suivante : n soit en passant par ses accesseurs (getter
si prop est le nom de la propriété, le getter ou setter)
doit être getProp (ou isProp si la propriété ‰ Le type d’accès est déterminé par
est de type boolean) et le setter setProp l’emplacement des annotations (associées aux
‰ Souvent une propriété correspond à une variables d’instance ou aux getter)
variable d’instance
R. Grin JPA page 25 R. Grin JPA page 26

Accès par propriété


Vocabulaire JPA
‰ Les accesseurs (setter et getter) doivent être
protected ou public ‰ Un champ désigne une variable d’instance
‰ Ils peuvent contenir d’autres instructions que
‰ JPA parle de propriété lorsque l’accès se fait
le seul code lié à la valeur de la variable en passant par les accesseurs (getter ou
sous-jacente setter)
‰ Ces instructions seront exécutées par le
‰ Lorsque le type d’accès est indifférent, JPA
fournisseur de persistance parle d’attribut
‰ Si une exception est levée par un accesseur,
la transaction est invalidée ; les exceptions
contrôlées sont enveloppées par une
PersistenceException (non contrôlée,
sous RuntimeException)
R. Grin JPA page 27 R. Grin JPA page 28

Choix du type d’accès Attributs persistants


‰ Le choix doit être le même pour toutes les ‰ Par défaut, tous les attributs d’une entité sont
classes d’une hiérarchie d’héritage (interdit de persistants
mélanger les 2 façons)
‰ L’annotation @Basic indique qu’un attribut
‰ En programmation objet il est conseillé d’utiliser
est persistant mais elle n’est donc
plutôt les accesseurs que les accès directs aux indispensable que si on veut préciser des
champs (meilleur contrôle des valeurs) ; c’est informations sur cette persistance (par
aussi le cas avec JPA exemple, une récupération retardée)
‰ Rappel : le choix est déterminé par
‰ Seuls les attributs dont la variable est
l'emplacement des annotations ; elles sont transient ou qui sont annotés par
associées soit aux accesseurs, soit aux @Transient ne sont pas persistants
variables d'instance ; ne pas mélanger les 2 !
R. Grin JPA page 29 R. Grin JPA page 30

5
Cycle de vie d’une instance d’entité Cycle de vie d’une instance d’entité
n détachée : elle a une identité dans la base
‰ L’instance peut être mais elle n’est plus associée à un contexte
n nouvelle (new) : elle est créée mais pas de persistance (une entité peut devenir
associée à un contexte de persistance détachée à la fin d’une transaction ou par
n gérée par un gestionnaire de persistance ; un passage par valeur en paramètre d’une
elle a une identité dans la base de données méthode distante)
(un objet peut devenir géré par la méthode n supprimée : elle a une identité dans la
persist, ou merge d’une entité détachée, base ; elle est associée à un contexte de
ou si c’est une instance « récupérée » dans persistance et ce contexte doit la
la base par une requête) supprimer de la base de données (passe
dans cet état par la méthode remove)
R. Grin JPA page 31 R. Grin JPA page 32

Cycle de vie d’une entité Les tables de la base de données


‰ 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 données de la classe
Departement sont enregistrées dans la table
Departement (ou DEPARTEMENT) dont les
J’ai oublié où j’ai pris cette image… merci de me colonnes se nomment id, nom, lieu
donner la référence si vous le savez
R. Grin JPA page 33 R. Grin JPA page 34

Configuration « par exception » Nom de table


‰ La configuration des classes entités suppose
‰ Pour donner à la table un autre nom que le
des valeurs par défaut
non de la classe, il faut ajouter une
‰ Il n’est nécessaire d’ajouter des informations annotation @Table
de configuration que si ces valeurs par
‰ Exemple :
défauts ne conviennent pas @Entity
‰ Par exemple, @Entity suppose que la table @Table(name="AUTRENOM")
qui contient les données des instances de la public class Classe {
classe a le même nom que la classe ...
}

R. Grin JPA page 35 R. Grin JPA page 36

6
Nom de colonne Classe Embeddable
‰ Les entités persistantes ne sont pas les seules
‰ Pour donner à une colonne de la table un autre classes persistantes
nom que le nom de l’attribut correspondant, il
‰ Il existe aussi des classes « insérées » ou
faut ajouter une annotation @Column
« incorporées » (embedded) dont les données
‰ Cette annotation peut aussi comporter des
n’ont pas d’identité dans la BD mais sont
attributs pour définir plus précisément la insérées dans une des tables associées à une
colonne entité persistante
‰ Exemple :
‰ Elles peuvent être annotées comme les entités
@Column(name="AUTRENOM",
updatable=false, length=80) (avec @Column par exemple)
public String getTruc() { ... } ‰ Par exemple, une classe Adresse dont les
valeurs sont insérées dans la table Employe
R. Grin JPA page 37 R. Grin JPA page 38

Classe Embeddable Exemple


@Embeddable
‰ Comme les entités, ces classes doivent avoir public class Adresse {
un constructeur sans paramètre private int numero;
‰ Les types permis pour leurs attributs sont les private String rue;
mêmes que les types permis pour les private String ville;
attributs des entités . . .
}
@Entity
public class Employe {
@Embedded private Adresse adresse;
...
Rappel : à mettre sur getAdresse()
R. Grin JPA page 39 R. Grin si accès JPA
par propriété page 40

Restrictions Classes insérées partagées


‰ La version actuelle de JPA a plusieurs ‰ Une classe entité peut référencer plusieurs
restrictions (peut-être enlevées dans une instances d’une même classe insérée
prochaine version) : ‰ Par exemple, la classe Employe peut
n une entité ne peut posséder une collection comporter l’adresse du domicile et l’adresse
d’objets insérés du travail des employés
n un objet inséré ne peut référencer un autre ‰ En ce cas, les noms des colonnes dans la
objet inséré ni avoir une association avec table de l’entité ne peuvent être les mêmes
une entité pour chacune des utilisations
‰ Un objet inséré ne peut être référencé par ‰ L’annotation @AttributeOverride peut
plusieurs entités différentes résoudre le problème
R. Grin JPA page 41 R. Grin JPA page 42

7
@AttributeOverride(s) Exemple
‰ Un champ annoté par @Embedded peut être @Entity
complété par une annotation public class Employe {
@AttributeOverride, ou plusieurs de ces @Embedded
annotations insérées dans une annotation @AttributeOverrides({
@AttributeOverrides @AttributeOverride(
name="ville",
‰ Ces annotations permettent d’indiquer le nom
column=@column(name="villeTravail")),
d’une ou de plusieurs colonnes dans la table
de l’entité @AttributeOverride(...)
})
‰ Elles peuvent aussi être utilisées si une
// Adresse du travail
classe insérée est référencée par plusieurs
private Adresse adresseTravail;
classes entités différentes
R. Grin JPA page 43 R. Grin JPA page 44

Annotation pour LOB Annotation pour énumération


‰ L’annotation @Lob permet d’indiquer qu’un ‰ Une annotation spéciale n’est pas nécessaire
attribut est un LOB (Large OBject) : soit un si un attribut est de type énumération si
CLOB (Character LOB, tel un long résumé de l’énumération est sauvegardée dans la BD
livre), soit un BLOB (Binary LOB, tel une sous la forme des numéros des constantes
image ou une séquence vidéo) de l’énumération (de 0 à n)
‰ Le fournisseur de persistance pourra ainsi ‰ Si on souhaite sauvegarder les constantes
éventuellement traiter l’attribut de façon sous la forme de la forme d’une String qui
spéciale (utilisation de flots d’entrées-sorties représente le nom de la valeur de
par exemple) l’énumération, il faut utiliser l’annotation
‰ Exemple : @Lob private byte[] image @Enumerated
R. Grin JPA page 45 R. Grin JPA page 46

Exemple Types temporels


‰ Lorsqu'une classe entité a un attribut de type
@Enumerated(EnumType.STRING) temporel (Calendar ou Date de
private TypeEmploye typeEmploye; 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 déclarer la
colonne correspondante dans la base de
données : une date (un jour), un temps sur 24
heures (heures, minutes, secondes à la
milliseconde près) ou un timeStamp (date +
heure à la microseconde près)
R. Grin JPA page 47 R. Grin JPA page 48

8
Annotation pour les types temporels Exemple
‰ 3 types temporels dans l’énumération
@Temporal(TemporalType.DATE)
TemporalType : DATE, TIME, TIMESTAMP
private Calendar dateEmb;
‰ Correspondent aux 3 types de SQL ou du
paquetage java.sql : Date, Time et
Timestamp

R. Grin JPA page 49 R. Grin JPA page 50

Tables multiples Schéma relationnel


‰ Dans le cas où le schéma relationnel est
‰ Il est possible de sauvegarder une entité sur construit automatiquement à partir des
plusieurs tables annotations, il est possible de préciser des
‰ Voir @SecondaryTable dans la spécification informations sur les tables générées ou les
JPA colonnes de ces tables
‰ C’est surtout utile pour les cas où la base de ‰ Par exemple, une contrainte d'unicité, ou "not
données existe déjà et ne correspond pas null", la longueur des colonnes de type
tout à fait au modèle objet varchar, la pré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
R. Grin JPA page 51 R. Grin JPA page 52

Exemple
@Entity
@Table(name="PARTICIPATION2",
uniqueConstraints =
@UniqueConstraint(
Gestionnaire d’entités
columnNames = (Entity Manager), GE
{"EMPLOYE_ID", "PROJET_ID"})
)
public class Participation {
...
}

R. Grin JPA page 53 R. Grin JPA page 54

9
Principe de base Unité de persistance
‰ La persistance des entités n’est pas ‰ C’est une configuration nommée qui contient les
transparente informations nécessaires à l’utilisation d’une base
‰ Une instance d’entité ne devient persistante de données
que lorsque l’application appelle la méthode ‰ Elle est associée à un ensemble de classes
appropriée du gestionnaire d’entité (persist entités
ou merge)
‰ Cette conception a été voulue par les
concepteurs de l’API par souci de flexibilité et
pour permettre un contrôle fin de l’application
sur la persistance des entités
R. Grin JPA page 55 R. Grin JPA page 56

Configuration d’une unité de Contexte de persistance


persistance ‰ Un contexte de persistance est un ensemble
d’entités qui vérifie la propriété suivante : il ne
‰ Dans un environnent non géré par un serveur peut exister 2 entités différentes qui représentent
d’applications, les informations sur une unité de des données identiques dans la base
persistance sont données dans un fichier
‰ Un contexte de persistance est géré par un
persistence.xml situé dans un sous-
gestionnaire d’entités qui veille à ce que cette
répertoire META-INF d’un des répertoires du
propriété soit respectée
classpath
‰ Un contexte de persistance ne peut appartenir
‰ Voir section « Configuration de l’unité de
qu’à une seule unité de persistance
persistance » dans la suite du cours
‰ Une unité de persistance peut contenir plusieurs
contextes de persistance
R. Grin JPA page 57 R. Grin JPA page 58

Contexte de persistance Contexte de persistance


‰ C’est la responsabilité de l’application de ‰ Quand une entité est incluse dans un
s’assurer qu’une entité n’appartient qu’à un contexte de persistance (persist ou
seul contexte de persistance merge), l’état de l’entité est automatiquement
‰ Sinon, 2 entités de 2 contextes de sauvegardé dans la base au moment de la
persistance différents pourraient validation (commit) de la transaction
correspondre à des données identiques dans
la base de données

R. Grin JPA page 59 R. Grin JPA page 60

10
Interface EntityManager Types de GE
‰ Elle représente un GE ‰ GE géré par le container (uniquement
disponible dans un serveur d’applications)
‰ Implémentation fournie par le fournisseur de
n délimité par les transactions
persistance
(TRANSACTION)
n peut survivre à une fin de transaction
(EXTENDED) ; nécessite un bean session
avec état (stateful)
‰ GE géré par l’application (seul type disponible
en dehors d’un serveur d’applications) ; pas
délimité par les transactions
R. Grin JPA page 61 R. Grin JPA page 62

GE non géré par le conteneur


‰ Ce cours présente l’utilisation de JPA en ‰ En dehors d’un serveur d’application, c’est
dehors du container d’un serveur l’application qui décide de la durée de vie
d’application d’un GE
‰ Voir la dernière section de ce cours pour des ‰ La méthode createEntityManager() de
informations sur JPA dans une serveur la classe EntityManagerFactory créé un
d’application GE
‰ Le GE est supprimé avec la méthode
close() de la classe EntityManager

R. Grin JPA page 63 R. Grin JPA page 64

Fabrique de GE Méthodes de EntityManager


‰ La classe Persistence permet d’obtenir une ‰ void persist(Object entité)
fabrique de gestionnaire d’entités par la ‰ <T> T merge(T entité)
méthode createEntityManagerFactory
‰ void remove(Object entité)
‰ 2 variantes surchargées de cette méthode :
‰ <T> T find(Class<T> classeEntité,
n 1 seul paramètre qui donne le nom de l’unité
Object cléPrimaire)
de persistance (définie dans le fichier
‰ <T> T getReference(Class<T>
persistence.xml)
classeEntité, Object cléPrimaire)
n Un 2ème paramètre de type Map qui contient
‰ void flush()
des valeurs qui vont écraser les propriétés
par défaut contenues dans persistence.xml ‰ void setFlushMode(FlushModeType
flushMode)
R. Grin JPA page 65 R. Grin JPA page 66

11
Méthodes de EntityManager Méthodes de EntityManager
‰ void lock(Object entité, ‰ Query createNativeQuery(String
LockModeType lockMode) requête)
‰ void refresh(Object entité) ‰ Query createNativeQuery(String
‰ void clear() requête, Class classeRésultat)
‰ boolean contains(Object entité) ‰ void joinTransaction()

‰ Query createQuery(String requête) ‰ void close()

‰ Query createNamedQuery(String nom) ‰ boolean isOpen()


‰ EntityTransaction getTransaction()

R. Grin JPA page 67 R. Grin JPA page 68

flush flush

‰ Toutes les modifications effectuées sur les ‰ Un flush est automatiquement effectué au
entités du contexte de persistance gérées par moins à chaque commit de la transaction en
le GE sont enregistrées dans la BD lors d’un cours
flush du GE ‰ Une exception
‰ Au moment du flush, le GE étudie ce qu’il doit TransactionRequiredException est
faire pour chacune des entités qu’il gère et il levée si la méthode flush est lancée en
lance les commandes SQL adaptées pour dehors d’une transaction
modifier la base de données (INSERT,
UPDATE ou DELETE)

R. Grin JPA page 69 R. Grin JPA page 70

flush Mode de flush


‰ Soit X une des entités gérée, avec une ‰ Normalement (mode FlushMode.AUTO) un
association de X vers une entité Y flush des entités concernées par une requête
‰ Si cette association est notée avec est effectué avant la requête pour que le
cascade=persist ou cascade=all, Y est résultat tienne compte des modifications
elle aussi flushée effectuées en mémoire sur ces entités
‰ Il est possible d'éviter ce flush avec la
‰ Sinon, si Y est new ou removed, une
méthode setFlushMode :
exception IllegalStateException sera em.setFlushMode(FlushMode.COMMIT);
levée et la transaction est invalidée (rollback)
‰ En ce cas, un flush ne sera lancé qu'avant un
‰ Sinon, si Y est détachée et X possède commit
l’association, Y est flushée ; si Y est la ‰ Il est possible de modifier ce mode pour une
propriétaire, le comportement est indéfini seule requête (voir Query)
R. Grin JPA page 71 R. Grin JPA page 72

12
persist persist(A)
‰ Si A est nouvelle, elle devient gérée
‰ Une entité « nouvelle » devient une entité
‰ Si A était déjà gérée, persist est ignorée
gérée
mais l’opération persist « cascade » sur les
‰ L’état de l’entité sera sauvegardé dans la BD
entités associées si l’association a l’attribut
au prochain flush ou commit CascadeType.PERSIST
‰ Aucune instruction ne sera nécessaire pour
‰ Si A est supprimée, elle devient gérée
faire enregistrer au moment du commit dans
la base de données les modifications ‰ Si A est détachée, une
IllegalArgumentException est lancée
effectuées sur l’entité par l’application ; en
effet le GE conserve toutes les informations ‰ Ne peut être utilisé que dans le contexte
nécessaires sur les entités qu’il gère d’une transaction
R. Grin JPA page 73 R. Grin JPA page 74

remove remove(A)

‰ Une entité gérée devient « supprimée » ‰ Ignorée si A est nouvelle ou supprimée


‰ Les données correspondantes seront ‰ Si A est nouvelle, l’opération « cascade » sur
supprimées de la BD les associations qui ont l’attribut
CascadeType.REMOVE
‰ Si A est gérée, elle devient supprimée
‰ Si A est détachée, une
IllegalArgumentException est lancée
‰ Ne peut être utilisé que dans le contexte
d’une transaction

R. Grin JPA page 75 R. Grin JPA page 76

refresh refresh(A)
‰ Le GE peut synchroniser avec la BD une ‰ Ignorée si A est nouvelle ou supprimée
entité qu’il gère en rafraichissant son état en
‰ Si A est nouvelle, l’opération « cascade » sur
mémoire avec les données actuellement
les associations qui ont l’attribut
dans la BD :
CascadeType.REFRESH
em.refresh(entite);
‰ Si A est détachée, une
‰ Les données de la BD sont copiées dans
IllegalArgumentException est lancée
l’entité
‰ Utiliser cette méthode pour s’assurer que
l’entité a les mêmes données que la BD
‰ Peut être utile pour les transactions longues

R. Grin JPA page 77 R. Grin JPA page 78

13
find lock(A)

‰ La recherche est polymorphe : l'entité ‰ Le fournisseur de persistance gère les accès


récupérée peut être de la classe passée en concurrents aux données de la BD
paramètre ou d'une sous-classe représentées par les entités avec une
‰ Exemple : stratégie optimiste
Article p = ‰ lock ermet de modifier la manière de gérer
em.find(Article.class, 128); les accès concurrents à une entité A
peut renvoyer un article de n'importe quelle ‰ Sera étudié plus loin dans la section sur la
sous-classe de Article (Stylo, concurrence
Ramette,…)

R. Grin JPA page 79 R. Grin JPA page 80

En dehors d’une transaction Entité détachée (1)


‰ Les méthodes suivantes (read only) peuvent
être lancées en dehors d’une transaction : ‰ Une application distribuée sur plusieurs
find, getReference, refresh et requêtes ordinateurs peut utiliser avec profit des
(query) entités détachées
‰ Les méthodes persist, remove, merge ‰ Une entité gérée par un GE peut être
peuvent être exécutées en dehors d’une détachée de son contexte de persistance
transaction mais elles seront enregistrées pour ‰ Elle peut ainsi être transférée en dehors de la
un flush dès qu’une transaction est active portée du GE
‰ Les méthodes flush, lock et modifications
de masse (executeUpdate) ne peuvent être
lancées en dehors d’une transaction
R. Grin JPA page 81 R. Grin JPA page 82

merge(A)
Entité détachée (2)
‰ Si A est une entité détachée, son état est copié
‰ Une entité détachée peut être modifiée dans une entité gérée A’ qui a la même identité
‰ Pour que ces modifications soient que A (si A’ n’existe pas déjà, il est créé) ;
enregistrées dans la BD, il est nécessaire de merge renvoie A’
rattacher l’entité à un GE par la méthode ‰ Si A est nouvelle, une nouvelle entité gérée A'
merge est créé et l’état de A est copié dans A’
‰ Si A est déjà gérée, merge est ignorée mais
merge « cascade » pour tous les associations
avec l’attribut CascadeType.MERGE
‰ Si A est supprimée, une
IllegalArgumentException est lancée
R. Grin JPA page 83 R. Grin JPA page 84

14
merge(A)

‰ Attention, la méthode merge n’attache pas A


‰ Elle retourne une entité gérée qui a la même
identité dans la BD que l’entité passée en
paramètre mais ça n’est pas le même objet Identité des entités

R. Grin JPA page 85 R. Grin JPA page 86

Clé primaire Annotation


‰ Une entité doit avoir un attribut qui ‰ L’attribut clé primaire est désigné par
correspond à la clé primaire dans la table l’annotation @Id
associée ‰ Pour une clé composite on utilise
‰ La valeur de cet attribut ne doit jamais être @EmbeddedId ou @IdClass
modifiée par l’application
‰ Cet attribut doit être défini dans l’entité racine
d’une hiérarchie d’héritage (uniquement à cet
endroit dans toute la hiérarchie d’héritage)
‰ Une entité peut avoir une clé primaire
composite (pas recommandé)
R. Grin JPA page 87 R. Grin JPA page 88

Type de la clé primaire Génération automatique de clé


‰ Le type de la clé primaire (ou des champs ‰ Si la clé est de type numérique entier,
d’une clé primaire composée) doit être un des l’annotation @GeneratedValue indique que
types suivants : la clé primaire sera générée automatiquement
n type primitif Java par le SGBD
n classe qui enveloppe un type primitif ‰ Cette annotation peut avoir un attribut
n java.lang.String strategy qui indique comment la clé sera
n java.util.Date
générée (il prend ses valeurs dans
l’énumération GeneratorType)
n java.sql.Date

‰ Ne pas utiliser les types numériques non


entiers
R. Grin JPA page 89 R. Grin JPA page 90

15
Types de génération Précisions sur la génération
‰ AUTO : le type de génération est choisi par le
‰ Les annotations @SequenceGenerator et
fournisseur de persistance, selon le SGBD @TableGenerator permettent de donner
(séquence, table,…) ; valeur par défaut
plus de précisions sur la séquence ou la table
‰ SEQUENCE : utilise une séquence est utilisée qui va permettre de générer la clé
‰ IDENTITY : une colonne de type IDENTITY ‰ Par exemple @SequenceGenerator permet
est utilisée de préciser la valeur initiale ou le nombre de
‰ TABLE : une table qui contient la prochaine clés récupérées à chaque appel de la
valeur de l’identificateur est utilisée séquence
‰ On peut aussi préciser le nom de la séquence ‰ Voir la spécification de JPA pour plus de
ou de la table avec l’attribut generator précisions
R. Grin JPA page 91 R. Grin JPA page 92

Exemple Clé composite


@Id ‰ Pas recommandé, mais une clé primaire peut
@GeneratedValue( être composée de plusieurs colonnes
strategy = GenerationType.SEQUENCE, ‰ Peut arriver quand la BD existe déjà ou
generator = "EMP_SEQ") quand la classe correspond à une table
public long getId() { association (association M:N)
return id;
‰ 2 possibilités :
}
n @IdClass

n @EmbeddedId et @Embeddable

R. Grin JPA page 93 R. Grin JPA page 94

Classe pour la clé composite @EmbeddedId


‰ Dans les 2 cas, la clé primaire doit être ‰ @EmbeddedId correspond au cas où la
représentée par une classe Java dont les classe entité comprend un seul attribut
attributs correspondent aux composants de la annoté @EmbeddedId
clé primaire ‰ La classe clé primaire est annoté par
‰ La classe doit être public, posséder un @Embeddable
constructeur sans paramètre, être sérialisable ‰ Le type d’accès (par champs ou propriétés)
et redéfinir equals et hashcode de la classe « embeddable » doit être le
même que celui de l’entité dont la clé
primaire est définie

R. Grin JPA page 95 R. Grin JPA page 96

16
Exemple avec @EmbeddedId @IdClass
@Entity
public class Employe { ‰ @IdClass correspond au cas où la classe
@EmbeddedId entité comprend plusieurs attributs annotés
private EmployePK employePK; par @Id
...
‰ La classe entité est annotée par @IdClass
}
qui prend en paramètre le nom de la classe
@Embeddable
public class EmployePK {
clé primaire
private String nom; ‰ La classe clé primaire n’est pas annotée ; ses
private Date dateNaissance; attributs ont les mêmes noms et mêmes
... types que les attributs annotés @Id dans la
} classe entité
R. Grin JPA page 97 R. Grin JPA page 98

Exemple avec @IdClass Quelle solution choisir ?


@Entity
@IdClass(EmployePK) ‰ @IdClass existe pour assurer une
public class Employe { compatibilité avec la spécification EJB 2.0
@Id private String nom;
‰ Quand c'est possible il vaut mieux utiliser
@Id Date dateNaissance;
@EmbeddedId
...
} ‰ @IdClass a aussi son utilité, par exemple,
public class EmployePK { pour les associations M:N si on veut que la
private String nom; clé primaire de la table association soit
private Date dateNaissance; composée des clés étrangères vers les tables
... qui sont associées (voir section sur les
} associations)
R. Grin JPA page 99 R. Grin JPA page 100

Généralités
‰ Une association peut être uni ou
bidirectionnelle
‰ Elle peut être de type 1:1, 1:N, N:1 ou M:N
Associations ‰ Les associations doivent être indiquées par
une annotation sur la propriété
correspondante, pour que JPA puisse les
gérer correctement

R. Grin JPA page 101 R. Grin JPA page 102

17
Exemple Représentation des associations
1:N et M:N
@ManyToOne
public Departement getDepartement() { ‰ Elles sont représentées par des collections ou
... maps qui doivent être déclarées par un des
}
types interface suivants (de java.util) :
n Collection

n Set

n List

n Map

‰ Les variantes génériques sont permises ; par


exemple Collection<Employe>
R. Grin JPA page 103 R. Grin JPA page 104

Types à utiliser Ordre dans les collections


‰ Le plus souvent Collection sera utilisé ‰ L’ordre d’une liste n'est pas nécessairement
‰ Set peut être utile pour éliminer les doublons préservé dans la base de données
‰ Les types concrets, par exemple HashSet ou ‰ De plus, l’ordre en mémoire doit être
ArrayList, ne peuvent être utilisés que maintenu par le code (pas automatique)
pour des entités « nouvelles » ; dès que ‰ Tout ce qu’on peut espérer est de récupérer
l’entité est gérée, les types interfaces doivent les entités associées dans la liste avec un
être utilisés certain ordre lors de la récupération dans la
‰ List peut être utilisé pour conserver un base, en utilisant l’annotation @OrderBy
ordre mais nécessite quelques précautions

R. Grin JPA page 105 R. Grin JPA page 106

@OrderBy
Exemples
‰ Cette annotation indique dans quel ordre sont
récupérées les entités associées @Entity
‰ Il faut préciser un ou plusieurs attributs qui public class Departement {
déterminent l'ordre ...
@OneToMany(mappedBy="departement")
‰ Chaque attribut peut être précisé par ASC ou
@OrderBy("nomEmploye")
DESC (ordre ascendant ou descendant);
ASC par défaut public List<Employe> getEmployes() {
...
‰ Les différents attributs sont séparés par une
virgule
@OrderBy("poste DESC, nomEmploye ASC")
‰ Si aucun attribut n'est précisé, l'ordre sera
celui de la clé primaire
R. Grin JPA page 107 R. Grin JPA page 108

18
Associations bidirectionnelles Bout propriétaire
‰ Le développeur est responsable de la gestion ‰ Pour les associations autres que M:N ce bout
correcte des 2 bouts de l’association correspond à la table qui contient la clé
‰ Par exemple, si un employé change de étrangère qui traduit l’association
département, les collections des employés ‰ Pour les associations M:N le développeur
des départements concernés doivent être peut choisir arbitrairement le bout propriétaire
modifiées ‰ L’autre bout (non propriétaire) est qualifié par
‰ Un des 2 bouts est dit « propriétaire » de l’attribut mappedBy qui donne le nom de
l’association l’attribut dans le bout propriétaire qui
correspond à la même association

R. Grin JPA page 109 R. Grin JPA page 110

Exemple Annotation @JoinColumn


‰ Dans la classe Employe : ‰ Cette annotation donne le nom de la colonne
@ManyToOne clé étrangère qui représente l'association
public Departement getDepartement() { dans le modèle relationnel
return departement;
} ‰ Elle doit être mise du côté propriétaire

‰ Dans la classe Departement : ‰ Sans cette annotation, le nom est défini par
@OneToMany(mappedBy="departement") défaut :
public Collection<Employe> getEmployes() { <entité_but>_<clé_primaire_entité_but>
return employes;
}

R. Grin JPA page 111 R. Grin JPA page 112

Exemple Persistance des objets associés


‰ Pour l'association qui détermine le ‰ Lorsqu’un objet o est rendu persistant
département d'un employé (méthode persist), les objets référencés
‰ Par défaut, la colonne clé étrangère placée par o devraient être rendus eux-aussi
dans la table EMPLOYE s'appellera persistants
Departement_ID ‰ Ce concept s’appelle la « persistance par
‰ Pour changer ce nom (dans la classe transitivité »
Employe) : ‰ Ça serait un comportement logique : un objet
@ManyToOne
n’est pas vraiment persistant si une partie
@JoinColumn(name="DEPT_ID")
public Departement getDepartement() { des valeurs de ses propriétés n’est pas
persistante
R. Grin JPA page 113 R. Grin JPA page 114

19
Pas si simple Le choix de JPA
‰ Maintenir une cohérence automatique des ‰ Par défaut, JPA n’effectue pas de persistance
valeurs persistantes n’est pas si simple en par transitivité
cas de persistance par transitivité ‰ Ce comportement permet plus de souplesse,
‰ Par exemple, que se passe-t-il si un objet et un meilleur contrôle de l’application sur ce
supprimé est référencé par un autre objet ? qui est rendu persistant
‰ Pour que les objets associés à un objet
persistant deviennent automatiquement
persistants, il faut l’indiquer dans les
informations de mapping de l’association
(attribut cascade)
R. Grin JPA page 115 R. Grin JPA page 116

Attribut cascade Exemples


‰ Les annotations qui décrivent les associations ‰ @OneToMany(
entre objets peuvent avoir un attribut cascade cascade=CascadeType.PERSIST)
‰ @OneToMany(
pour indiquer que certaines opérations de GE
cascade={CascadeType.PERSIST,
doivent être appliquées aux objets associés CascadeType.MERGE})
‰ Ces opérations sont PERSIST, REMOVE,
REFRESH et MERGE ; ALL correspond à toutes
ces opérations
‰ Par défaut, aucune opération n’est appliquée
transitivement

R. Grin JPA page 117 R. Grin JPA page 118

Association 1:1 Associations 1:N et N:1


‰ Annotation @OneToOne ‰ Annotations @OneToMany et @ManyToOne
‰ Représentée par une clé étrangère dans la ‰ Représentée par une clé étrangère dans la
table qui correspond au côté propriétaire table qui correspond au côté propriétaire
‰ Exemple : (obligatoirement le côté « Many »)
@OneToOne
public Adresse getAdresse() {

}

R. Grin JPA page 119 R. Grin JPA page 120

20
Exemple Cas particulier
‰ class Employe {
... ‰ Une association monodirectionnelle 1:N est
@ManyToOne
public Departement getDepartement() { traduite pas une table association
... ‰ Cette façon de faire évite d'avoir une clé
} étrangère dans la table qui représente le côté
}
‰ class Departement {
« N » (comme c’est le cas si l’association est
... bidirectionnelle) alors que la navigation n’est
@OneToMany(MappedBy="departement") pas possible à partir de ce côté « N »
public List<Employe> getEmployes() {
...
}
}

R. Grin JPA page 121 R. Grin JPA page 122

Association M:N Association M:N (1)


‰ Annotation @ManyToMany ‰ Les valeurs par défaut :
n le nom de la table association est la
‰ Représentée par une table association
concaténation des 2 tables, séparées par
«_»
n les noms des colonnes clés étrangères sont
les concaténations de la table référencée,
de « _ » et de la colonne « Id » de la table
référencée

R. Grin JPA page 123 R. Grin JPA page 124

Association M:N (2) @JoinTable


‰ Si les valeurs par défaut ne conviennent pas, ‰ Donne des informations sur la table
le côté propriétaire doit comporter une association qui va représenter l’association
annotation @JoinTable ‰ Attribut name donne le nom de la table
‰ L’autre côté doit toujours comporter l’attribut ‰ Attribut joinColumns donne les noms des
mappedBy colonnes de la table qui référencent les clés
primaires du côté propriétaire de l’association
‰ Attribut inverseJoinColumns donne les
noms des colonnes de la table qui
référencent les clés primaires du côté qui
n’est pas propriétaire de l’association

R. Grin JPA page 125 R. Grin JPA page 126

21
Exemple (classe Employe) Exemple (classe Projet)
@ManyToMany @ManyToMany(mappedBy="projets")
@JoinTable( public Collection<Employe> getEmps() {
name="EMP_PROJET"
joinColumns=@JoinColumn(name="matr")
inverseJoinColumns=
@JoinColumn(name="codeProjet")
)
public Collection<Projet> getProjets() {

R. Grin JPA page 127 R. Grin JPA page 128

Association M:N avec information Classe association pour une


portée par l'association association M:N
‰ Une association M:N peut porter une ‰ L'association sera traduite par une classe
information association
‰ Exemple : ‰ 2 possibilités pour cette classe, suivant
Association entre les employés et les projets qu'elle contient ou non un attribut
Un employé a une (et une seule) fonction identificateur (@Id) unique
dans chaque projet auquel il participe ‰ Le plus simple est de n'avoir qu'un seul
‰ En ce cas, il n'est pas possible de traduire attribut identificateur
l'association en ajoutant 2 collections (ou
maps) comme il vient d'être décrit
R. Grin JPA page 129 R. Grin JPA page 130

Exemple - 1 identificateur Exemple - 2 identificateurs (1)


‰ Association entre les employés et les projets
‰ Si la base de données existe déjà, il sera
‰ Cas d'un identificateur unique : la classe
association contiendra les attributs id (int), fréquent de devoir s'adapter à une table
employe (Employe), projet (Projet) et association qui contient les colonnes
fonction (String) suivantes (pas de colonne id):
n employe_id, clé étrangère vers EMPLOYE
‰ L'attribut id est annoté par @Id
n projet_id, clé étrangère vers PROJET
‰ Les attributs employe et projet sont
annotés par @ManyToOne n fonction

‰ Une contrainte d'unicité sur (EMPLOYE_ID, ‰ et qui a (employe_id, projet_id) comme


PROJET_ID) traduira le fait qu'un employé ne clé primaire
peut avoir 2 fonctions dans un même projet
R. Grin JPA page 131 R. Grin JPA page 132

22
Exemple - 2 identificateurs (2) Exemple - 2 identificateurs
avec TopLink
‰ En ce cas, la solution est plus complexe, et ‰ La solution donnée dans les transparents
pas toujours portable dans l'état actuel de la suivants convient pour TopLink essentials
spécification JPA
‰ La difficulté vient de l'écriture de la classe
‰ La solution donnée dans les transparents Participation
suivants convient pour TopLink essentials
‰ L'idée est de dissocier la fonction
‰ La difficulté vient de l'écriture de la classe d'identificateur des attributs employeId et
Participation projetId de leur rôle dans les associations
‰ L'idée est de dissocier la fonction de clé avec les classes Projet et Employe
primaire des attributs employeId et projetId ‰ Pour éviter les doublons d'attributs, les
de leur rôle dans les associations identificateurs sont marqués non modifiables
ni insérables (pas de persistance dans la BD)
R. Grin JPA page 133 R. Grin JPA page 134

Classes Employe et Projet Classe Participation (début)


‰ @Entity public class Employe { @Entity
@Id public int getId() { ... } @IdClass(ParticipationId.class)
@OneToMany(mappedBy="employe") public class Participation {
public Collection<Participation>
getParticipations() { ... } // Les identificateurs "read-only"
. . . @Id
} @Column(name="EMPLOYE_ID",
‰ @Entity public class Projet { insertable="false", updatable="false")
@Id public int getId() { ... } public int getEmployeId() { … }
@OneToMany(mappedBy="projet") @Id
public Collection<Participation> @Column(name="PROJET_ID",
getParticipations() { ... } insertable="false", updatable="false")
. . .
} public int getProjetId() { … }
R. Grin JPA page 135 R. Grin JPA page 136

Classe Participation (fin) Classe ParticipationId


// Les associations
@OneToMany public class ParticipationId
public Employe getEmploye() { … } implements Serializable {
@OneToMany private int employeId;
private int projetId;
public Projet getProjet() { … }
public int getEmployeId() { ... }
. . . public void setEmployeId(int employeId)
} { ... }
public int getProjetId() { ... }
public void setProjetId(int projetId)
{ ... }
// Redéfinir aussi equals et hasCode

R. Grin JPA page 137 R. Grin JPA page 138

23
Récupération des entités associées EAGER ou LAZY
‰ JPA laisse le choix de récupérer ou non
‰ Lorsqu’une entité est récupérée depuis la
base de données par une requête (Query) ou immédiatement les entités associées, suivant
par un find, est-ce que les entités associées les circonstances
doivent être elles aussi récupérées ? ‰ Il suffit de choisir le mode de récupération de
l’association (LAZY ou EAGER)
‰ Si elles sont récupérées, est-ce que les entités
associées à ces entités doivent elles aussi ‰ Une requête sera la même, quel que soit le
être récupérées ? mode de récupération
‰ On voit que le risque est de récupérer un très ‰ Dans le mode LAZY les données associées
grand nombre d’entités qui ne seront pas ne sont récupérées que lorsque c’est
utiles pour le traitement en cours vraiment nécessaire
R. Grin JPA page 139 R. Grin JPA page 140

Récupération retardée (LAZY) Comportement par défaut de JPA


‰ Dans le cas où une entité associée n’est pas
récupérée immédiatement, JPA remplace ‰ Par défaut, JPA ne récupère immédiatement
l’entité par un « proxy », objet qui permettra que les entités associées par des
de récupérer l’entité plus tard si besoin est associations dont le but est « One » (une
seule entité à l’autre bout) : OneToOne et
‰ Ce proxy contient la clé primaire qui
ManyToOne (mode EAGER)
correspond à l’entité non immédiatement
‰ Pour les associations dont le but est
récupérée
« Many » (une collection à l’autre bout),
‰ Il est possible de lancer une requête avec
OneToMany et ManyToMany, par défaut, les
une récupération immédiate, même si une entités associées ne sont pas récupérées
association est en mode LAZY (join fetch de immédiatement (mode LAZY)
JPQL étudié plus loin)
R. Grin JPA page 141 R. Grin JPA page 142

Indiquer le type de récupération Mode de récupération


des entités associées des attributs
‰ Les attributs aussi peuvent être récupérés en
‰ L’attribut fetch d’une association permet mode « retardé »
d’indiquer une récupération immédiate des ‰ Le mode de récupération par défaut est le
entités associées (FetchType.EAGER) ou une mode EAGER pour les attributs (ils sont
récupération retardée (FetchType.LAZY) si le chargés en même temps que l’entité)
comportement par défaut ne convient pas ‰ Si un attribut est d’un type de grande
‰ Exemple : dimension (LOB), il peut aussi être marqué par
@OneToMany(mappedBy="departement", @Basic(fetch=FetchType.LAZY)
fetch=FetchType.EAGER)
public Collection<Employe> (à utiliser avec parcimonie)
getEmployes() ‰ Cette annotation n’est qu’une suggestion au
GE, qu’il peut ne pas suivre
R. Grin JPA page 143 R. Grin JPA page 144

24
Map pour association Map pour association
‰ A la place d’une collection il est possible ‰ Si l’association est traduite par une map mais
d’utiliser une map n’a pas d’annotation @KeyMap, la clé sera
‰ En ce cas il faut annoter l’association avec considérée être l’identificateur de l’entité
@MapKey qui précise la clé de la map qui doit
être un des attributs de l’entité contenue dans
la map
‰ La classe de la clé doit avoir sa méthode
hashCode compatible avec sa méthode
equals et chaque clé doit être unique parmi
toutes les autres clés de la map
R. Grin JPA page 145 R. Grin JPA page 146

Exemple
‰ Les employés d’un département peuvent être
enregistrés dans une map dont les clés sont
les noms des employés (on suppose que 2
employés n’ont pas le même nom)
Héritage
public class Departement {
...
@OneToMany(mappedBy="nom")
public Map<String,Employe> getEmployes(){
...
}
R. Grin JPA page 147 R. Grin JPA page 148

Stratégies Une table par hiérarchie


‰ A ce jour, les implémentations de JPA doivent
‰ Sans doute la stratégie la plus utilisée
obligatoirement offrir 2 stratégies pour la
traduction de l’héritage : ‰ Valeur par défaut de la stratégie de traduction
de l’héritage
n une seule table pour une hiérarchie
d’héritage (SINGLE_TABLE) ‰ Elle est performante et permet le
polymorphisme
n une table par classe ; les tables sont jointes
pour reconstituer les données (JOINED) ‰ Mais elle induit beaucoup de valeurs NULL
dans les colonnes si la hiérarchie est
‰ La stratégie « une table distincte par classe
complexe
concrète » est seulement optionnelle
(TABLE_PER_CLASS)
R. Grin JPA page 149 R. Grin JPA page 150

25
Exemple Nom de la table
@Entity A mettre dans la
classe racine de ‰ Si on choisit la stratégie « une seule table
@Inheritance(strategy= la hiérarchie pour une arborescence d’héritage » la table a
InheritanceType.SINGLE_TABLE) le nom de la table associée à la classe racine
public abstract class Personne {...} de la hiérarchie

@Entity
« Employe » par défaut
@DiscriminatorValue("E")
public class Employe extends Personne {
...
}

R. Grin JPA page 151 R. Grin JPA page 152

Colonne discriminatrice (1) Colonne discriminatrice (2)


‰ Une colonne de la table doit permettre de ‰ L’annotation @DicriminatorColumn
différencier les lignes des différentes classes permet de modifier les valeurs par défaut
de la hiérarchie d’héritage ‰ Ses attributs :
‰ Cette colonne est indispensable pour le bon n name
fonctionnement des requêtes qui se limitent à n discriminatorType
une sous-classe
n columnDefinition fragment SQL pour
‰ Par défaut, cette colonne se nomme DTYPE
créer la colonne
et elle est de type Discriminator.STRING
n length longueur dans le cas où le type
de longueur 31 (autres possibilités pour le
type : CHAR et INTEGER) est STRING (31 par défaut)

R. Grin JPA page 153 R. Grin JPA page 154

Exemple Valeur discriminatrice


@Entity ‰ Chaque classe est différenciée par une
@Inheritance valeur de la colonne discriminatrice
@DiscriminatorColumn(
‰ Cette valeur est passée en paramètre de
name="TRUC",
discriminatorType="STRING",
l’annotation @DiscriminatorValue
length=5) ‰ Par défaut cette valeur est le nom de la
public class Machin { classe

}

R. Grin JPA page 155 R. Grin JPA page 156

26
Une table par classe Exemple
‰ Toutes les classes, même les classes
abstraites, sont représentées par une table @Entity
@Inheritance(strategy=
‰ Nécessite des jointures pour retrouver les InheritanceType.JOINED)
propriétés d’une instance d’une classe public abstract class Personne {...}
‰ Une colonne discriminatrice est ajoutée dans
la table qui correspond à la classe racine de @Entity
la hiérarchie d’héritage @DiscriminatorValue("E")
‰ Cette colonne permet de simplifier certaines
public class Employe extends Personne {
...
requêtes ; par exemple, pour retrouver les }
noms de tous les employés (classe Personne
à la racine de la hiérarchie d’héritage)
R. Grin JPA page 157 R. Grin JPA page 158

Une table par classe concrète Exemple


‰ Stratégie seulement optionnelle ‰ @Entity
@Inheritance(strategy=
‰ Pas recommandé car le polymorphisme est InheritanceType.TABLE_PER_CLASS)
plus complexe à obtenir (voir cours sur le public abstract class Personne {...}
mapping objet-relationnel) ‰ @Entity
‰ Chaque classe concrète correspond à une @Table(name=EMPLOYE)
seule table totalement séparée des autres public class Employe extends Personne {
...
tables
}
‰ Toutes les propriétés de la classe, même celles
qui sont héritées, se retrouvent dans la table

R. Grin JPA page 159 R. Grin JPA page 160

Entité abstraite Compléments


‰ Une classe abstraite peut être une entité ‰ L’annotation @Entity ne s’hérite pas
(annotée par @Entity) ‰ Les sous-classes entités d’une entité doivent
‰ Son état sera persistant et sera utilisé par les être annotée par @Entity
sous-classes entités ‰ Une entité peut avoir une classe mère qui
‰ Comme toute entité, elle pourra désigner le n’est pas une entité ; en ce cas, l’état de cette
type retour d’une requête (query) pour une classe mère ne sera pas persistant
requête polymorphe

R. Grin JPA page 161 R. Grin JPA page 162

27
Classe mère persistante Classe mère persistante
‰ Une entité peut aussi avoir une classe mère ‰ Cette classe mère ne pourra pas être
dont l’état est persistant, sans que cette renvoyée par une requête, ne pourra pas être
classe mère ne soit une entité passée en paramètre d’une méthode d’un
‰ En ce cas, la classe mère doit être annotée EntityManager ou d’un Query et ne pourra
par @MappedSuperclass être le but d’une association
‰ L’état de cette classe mère sera rendu
persistant avec l’état de la classe entité fille,
dans la même table que cette classe entité

R. Grin JPA page 163 R. Grin JPA page 164

Classe mère « non persistante »


‰ Une classe entité peut aussi hériter d’une
classe mère dont l’état n’est pas persistant
‰ En ce cas, l’état hérité de la classe mère ne
sera pas persistant Requêtes - JPQL
‰ La classe mère ne comportera aucune
annotation particulière liée à la persistance

R. Grin JPA page 165 R. Grin JPA page 166

Chercher par identité getReference


‰ find et getReference (de EntityManager)
‰ getReference renvoie une référence vers une
permettent de retrouver une entité en donnant
son identificateur dans la BD entité, sans que cette entité ne soit
nécessairement initialisée
‰ Elles prennent 2 paramètres de type
‰ Le plus souvent il vaut mieux utiliser find
n Class<T> pour indiquer le type de l’entité

recherchée (le résultat renvoyé sera de cette


classe ou d'une sous-classe)
n Object pour indiquer la clé primaire

‰ Exemple :
Departement dept =
em.find(Departement.class, 10);
R. Grin JPA page 167 R. Grin JPA page 168

28
getReference Étapes pour récupérer des données
‰ getReference peut être (rarement) utilisée ‰ Souvent il est nécessaire de rechercher des
données sur des critères plus complexes que
pour améliorer les performances quand une
la simple identité
entité non initialisée peut être suffisante, sans
que l’entité entière soit retrouvée dans la base ‰ Les étapes sont alors les suivantes :
de données 1. Décrire ce qui est recherché (langage

‰ Par exemple, pour indiquer une association dont JPQL)


le but est unique (OneToOne ou ManyToOne) : 2. Créer une instance de type Query
Departement dept = 3. Initialiser la requête (paramètres,
em.getReference(Departement.class, 10);
Employe emp.setDepartement(dept);
pagination)
4. Lancer l’exécution de la requête

R. Grin JPA page 169 R. Grin JPA page 170

Langage JPQL Requêtes sur les entités « objet »


‰ Le langage JPQL (Java Persistence Query ‰ Les requêtes travaillent avec le modèle objet
Language) permet de décrire ce que et pas avec le modèle relationnel
l’application recherche ‰ Les identificateurs désignent les classes et
‰ Il ressemble beaucoup à SQL leurs propriétés et pas les tables et leurs
colonnes
‰ Les seules classes qui peuvent être
explicitement désignées dans une requête
(clause from) sont les entités

R. Grin JPA page 171 R. Grin JPA page 172

Alias Exemples de requêtes


‰ Le texte des requêtes utilise beaucoup les ‰ select e from Employe as e
alias de classe ‰ select e.nom, e.salaire from Employe e
‰ select e from Employe e
‰ Les attributs des classes doivent être préfixés
where e.departement.nom = 'Direction'
par les alias
‰ select d.nom, avg(e.salaire)
‰ Une erreur fréquente du débutant est from Departement d join d.employes e
d’oublier les alias en préfixe group by d.nom
having count(d.nom) > 5

R. Grin JPA page 173 R. Grin JPA page 174

29
Type du résultat Obtenir le résultat de la requête
‰ L’expression de la clause select peut être ‰ Pour le cas où une seule valeur ou entité est
n une (ou plusieurs) expression « entité »,
renvoyée, le plus simple est d’utiliser la
par exemple un employé (e par exemple) méthode getSingleResult() ; elle renvoie
un Object
n une (ou plusieurs) expression « valeur »,
par exemple le nom et le salaire d’un
employé (e.nom par exemple)
‰ L’expression ne peut être une collection
(d.employes par exemple), bien que
TopLink le permette !

R. Grin JPA page 175 R. Grin JPA page 176

Obtenir le résultat de la requête Type d’un élément


du résultat
‰ Pour le cas où une plusieurs valeurs ou
entités peuvent être renvoyées, il faut utiliser
‰ Le type d’un élément de la liste (ou de
la méthode getResultList()
l’unique valeur ou entité renvoyée) est
‰ Elle renvoie une liste « raw » (pas générique)
n Object si la clause select ne comporte
des résultats, instance de java.util.List
qu’une seule expression
‰ Un message d’avertissement sera affiché
n Object[] si elle comporte plusieurs
durant la compilation si le résultat est rangé
expressions
dans une liste générique (Liste<Employe>
par exemple)

R. Grin JPA page 177 R. Grin JPA page 178

Exemple Interface Query


texte = "select e.nom, e.salaire " ‰ Représente une requête
+ " from Employe as e"; ‰ Une instance de Query (d’une classe
query = em.createQuery(texte); implémentant Query) est obtenue par les
List<Object[]> liste = méthodes createQuery, createNativeQuery
(List<Object[]>)query.getResultList();
ou createNamedQuery de l’interface
for (Object[] info : liste) { EntityManager
System.out.println(info[0] + " gagne "
+ info[1]);
}

R. Grin JPA page 179 R. Grin JPA page 180

30
Méthodes de Query (1) Méthodes de Query (2)
‰ List getResultList() ‰ Query setParameter(String nom,
‰ Object getSingleResult() Object valeur)
‰ int executeUpdate() ‰ Query setParameter(String nom,

‰ Query setMaxResults(int
Date valeur, TemporalType
nbResultats) typeTemporel)
‰ Query setParameter(String nom,
‰ Query setFirstResult(int
positionDepart) Calendar valeur, TemporalType
typeTemporel)
‰ Query setFlushMode(FlushModeType
modeFlush)

R. Grin JPA page 181 R. Grin JPA page 182

Types temporels Exemple


‰ On a vu que les 2 types java temporels du ‰ @Temporal(TemporalType.DATE)
paquetage java.util (Date et Calendar) private Calendar dateEmb;
nécessitent une annotation @Temporal ‰ em.createQuery("select e from employe e"
+ " where e.dateEmb between ?1 and ?2")
‰ Ils nécessitent aussi un paramètre .setParameter(1, debut, TemporalType.DATE)
supplémentaire pour la méthode .setParameter(2, fin, TemporalType.DATE)
setParameter .getResultList();

R. Grin JPA page 183 R. Grin JPA page 184

Types de requête Exemple de requête nommée


‰ Requêtes dynamiques dont le texte est @Entity
donnée en paramètre de createQuery @NamedQuery{
‰ Requêtes natives particulières à un SGBD name = "findNomsEmployes",
(pas portables) ; requête SQL (pas JPQL) query = "select e.nom from Employe as e
avec tables et colonnes (pas classes et where upper(e.departement.nom) = :nomDept"
attributs) }
public class Employe extends Personne {
‰ Requêtes nommées dont le texte est donnée
...
dans une annotation de l’entité concernée et
dont le nom est passé en paramètre de
Query q =
createNamedQuery ; une requête nommée
em.createNamedQuery("findNomsEmployes");
peut être dynamique ou native
R. Grin JPA page 185 R. Grin JPA page 186

31
Paramètres des requêtes Exemples
‰ Un paramètre peut être désigné par son ‰ Query query = em.createQuery(
numéro (?n) ou par son nom (:nom) "select e from Employe as e "
+ "where e.nom = ?1");
‰ Les valeurs des paramètres sont données query.setParameter(1, "Dupond");
par les méthodes setParameter ‰ Query query = em.createQuery(
‰ Les paramètres sont numérotés à partir de 1 "select e from Employe as e "
+ "where e.nom = :nom");
‰ Un paramètre peut être utilisé plus d’une fois
query.setParameter("nom", "Dupond");
dans une requête
‰ L’usage des paramètres nommés est
recommandé (plus lisible)

R. Grin JPA page 187 R. Grin JPA page 188

Mode de flush
‰ Normalement (mode FlushMode.AUTO) un ‰ Les transparents suivants étudient en détails
flush des entités concernées par une requête le langage JPQL
est effectué avant la requête pour que le
résultat tienne compte des modifications
effectuées en mémoire sur ces entités
‰ Pour une requête il est possible d'éviter ce
flush avec la méthode setFlushMode :
query.setFlushMode(FlushMode.COMMI
T);

R. Grin JPA page 189 R. Grin JPA page 190

Clauses d’un select


‰ select : type des objets ou valeurs ‰ Les mots-clés select, from, distinct,
renvoyées join,… sont insensibles à la casse
‰ from : où les données sont récupérées
‰ where : sélectionne les données
‰ group by : regroupe des données
‰ having : sélectionne les groupes (ne peut
exister sans clause group by)
‰ order by : ordonne les données

R. Grin JPA page 191 R. Grin JPA page 192

32
Polymorphisme dans les requêtes Expression de chemin
‰ Toutes les requêtes sont polymorphes : un ‰ Les requêtes peuvent contenir des
nom de classe dans la clause from désigne expressions de chemin pour naviguer entre
cette classe et toutes les sous-classes les entités en suivant les associations
‰ Exemple : déclarées dans le modèle objet (les
select count(a) from Article as a annotations @OneToOne, @OneToMany, …)
compte le nombre d’instances de la classe ‰ La notation « pointée » est utilisée
Article et de tous les sous-classes de
Article

R. Grin JPA page 193 R. Grin JPA page 194

Exemples distinct

‰ Si e est un alias pour Employe, ‰ Dans une clause select, indique que les
n « e.departement » désigne le valeurs dupliquées sont éliminées (la requête
département d’un employé ne garde qu’une seule des valeurs égales)
n « e.projets » désigne la collection de ‰ Exemple :
projets auxquels participe un employé select distinct e.departement
‰ select e.nom from Employe e
from Employe as e
where e.departement.nom = 'Qualité'

R. Grin JPA page 195 R. Grin JPA page 196

new Clauses where et having


‰ Il est possible de renvoyer des instances d’une ‰ Ces clauses peuvent comporter les mots-clés
classe dont le constructeur prend en paramètre suivants :
des informations récupérées dans la base de n [NOT] LIKE, [NOT] BETWEEN, [NOT] IN
données n AND, OR, NOT
‰ La classe doit être désignée par son nom
n [NOT] EXISTS
complet (avec le nom du paquetage)
n ALL, SOME/ANY
‰ Exemple :
n IS [NOT] EMPTY, [NOT] MEMBER OF
select new p1.p2.Classe(e.nom, e.salaire)
from Employe e

R. Grin JPA page 197 R. Grin JPA page 198

33
Exemple having
select d.nom, avg(e.salaire) ‰ Restriction : la condition doit porter sur
from Departement d join d.employes e l’expression de regroupement ou sur une
group by d.nom fonction de regroupement portant sur
having count(d.nom) > 3 l’expression de regroupement
‰ Par exemple, la requête suivante provoque
une exception :
select d.nom, avg(e.salaire)
from Departement d join d.employes e
group by d.nom
having avg(e.salaire) > 1000

R. Grin JPA page 199 R. Grin JPA page 200

Sous-requête (1) Sous-requête (2)


‰ Les clauses where et having peuvent ‰ {ALL | ANY | SOME} (sous-requête)
contenir des sous-requêtes fonctionne comme dans SQL
‰ Exemple : ‰ Exemple :
select e from Employe e select e from Employe e
where e.salaire >= ( where e.salaire >= ALL (
select e2.salaire from Employe e2 select e2.salaire from Employe e2
where e2.departement = 10) where e2.departement =
e.departement)

R. Grin JPA page 201 R. Grin JPA page 202

Sous-requête synchronisée Sous-requête - exists


‰ Une sous-requête peut être synchronisée ‰ [not]exists fonctionne comme avec SQL
avec une requête englobante ‰ Exemple :
‰ Exemple : select emp from Employe e
select e from Employe e where exists (
where e.salaire >= ALL ( select ee from Employe ee
select e2.salaire from Employe e2 where ee = e.epouse)
where e2.departement =
e.departement)

R. Grin JPA page 203 R. Grin JPA page 204

34
Règle pour les expressions Exemple
de chemin
select e.nom,
e.departement.nom,
‰ Une navigation peut être chaînée à une e.superieur.departement.nom
navigation précédente à la condition que la from Employe e
navigation précédente ne donne qu’une seule
entité (OneToOne ou ManyToOne)

R. Grin JPA page 205 R. Grin JPA page 206

Contre-exemple Jointure
‰ « d.employes.nom » est interdit car ‰ Une jointure permet de combiner plusieurs
d.employes est une collection entités dans un select
‰ Pour avoir les noms des employés d’un ‰ Rappel : il est possible d’utiliser plusieurs
département, il faut utiliser une jointure entités dans une requête grâce à la
navigation
‰ Une jointure est le plus souvent utilisée pour
résoudre les cas (interdit par JPA) où
n l’expression du select serait une collection

n la navigation partirait d’une collection

R. Grin JPA page 207 R. Grin JPA page 208

Types de jointures Exemple


‰ Il existe plusieurs types de jointures : ‰ Si on veut tous les employés d’un
n jointure interne (jointure standard join) département, la requête suivante n’est pas
n jointure externe (outer join)
permise par la spécification JPA (bien que
TopLink l’autorise) :
n jointure avec récupération de données en
select d.employes
mémoire (join fetch) from Departement d
where d.nom = 'Direction'
‰ Une jointure est nécessaire :
select e
from Departement d join d.employes e
where d.nom = 'Direction'
R. Grin JPA page 209 R. Grin JPA page 210

35
Autres exemples Jointure externe
‰ select e.nom
from Departement d ‰ select e, d
join d.employes e from Employe e left join e.departement d
where d.nom = 'Direction'
affichera aussi les employés qui ne sont pas
‰ select e.nom, parts.projet.nom
from Employe e associés à un département
join e.participations parts
‰ select e.nom, d.nom
from Employe e, Departement d
where d = e.departement
‰ select e, p
from Employe e
join e.participations parts
join parts.projet p
R. Grin JPA page 211 R. Grin JPA page 212

join fetch Exemple


‰ Permet d’éviter le problème des « N + 1 ‰ select e
selects » from Employe e join fetch e.departement

‰ L’entité placé à droite de fetch join sera ‰ Cette requête récupérera tous les employés
créée en mémoire en même temps que mais, en plus, l’appel de la méthode
l’entité de la clause select getDepartement() ne provoquera aucune
interrogation de la base de données puisque
‰ Le select SQL généré sera une jointure
le « join fetch » aura déjà chargé tous les
externe qui récupérera les données de toutes
départements des employés
les entités associées en même temps que les
données des entités principales de la requête ‰ L’exemple suivant précharge les collections
de participations aux projets
R. Grin JPA page 213 R. Grin JPA page 214

Exemple Doublons possibles avec join fetch


‰ La requête SQL lancée par un join fetch fait une
String texteQuery =
jointure pour récupérer les entités préchargées
"select e "
‰ Ensuite, les entités préchargées sont enlevées
+ " from Employe as e "
des lignes du résultat pour qu’elles
+ " join fetch e.participations";
n’apparaissent pas dans le résultat du query
Query query = em.createQuery(texteQuery);
‰ Ce traitement, imposé par la spécification de
listeEmployes =
(List<Employe>)query.getResultList(); JPA, peut occasionner des doublons dans le
résultat
‰ Pour les éviter, il faut ajouter l’opérateur
DISTINCT dans le texte de la requête ou placer
le résultat dans une collection de type Set
R. Grin JPA page 215 R. Grin JPA page 216

36
Fonctions Travail avec les collections
‰ Fonctions de chaînes de caractères : concat,
substring, trim, lower, upper, length, locate ‰ Une expression chemin d’un select peut
(localiser une sous-chaîne dans une autre) désigner une collection
‰ Exemples :
‰ Fonctions arithmétiques : abs, sqrt, mod, size
departement.employes
(d’une collection)
facture.lignes
‰ Fonctions de date : current_date, current_time,
‰ La fonction size donne la taille de la collection
current_timestamp
‰ La condition « is [not] empty » est vraie si
‰ Fonctions de regroupement : count, max, min,
avg la collection est [n’est pas] vide
‰ La condition « [not] member of » indique si
‰ Pour plus d’informations, consultez la
spécification JPA une entité appartient à une collection
R. Grin JPA page 217 R. Grin JPA page 218

Exemples Parcours d’une collection


‰ select d ‰ La requête suivante ne donnera pas tous les
from Departement produits liés à une facture ; elle provoquera
where e.employes is empty
une exception à l’exécution
‰ select e select distinct f.lignes.produit
from Employe e from Facture as f
where :projet member of
e.participations.projet ‰ En effet, il est interdit de composer une
expression de chemin en partant d’une
expression qui désigne une collection
(f.lignes)

R. Grin JPA page 219 R. Grin JPA page 220

Parcours d’une collection Enchaînement des méthodes


‰ Le plus simple est d’utiliser un join dans le ‰ Les méthodes setParameter,
from avec un alias (« l » dans l’exemple ci- setMaxResults renvoient le Query modifié
dessous) pour désigner un élément qui ‰ On peut donc les enchaîner
parcourt la collection : ‰ Exemple :
select distinct l.produit
em.createQuery(texteQuery)
from Facture as f join f.lignes as l
.setParameter(nomParam, valeurParam)
‰ L’autre solution, « in », une ancienne syntaxe .setMaxResults(30)
héritée d’EJB 2, n’est pas recommandée .getResultList();

R. Grin JPA page 221 R. Grin JPA page 222

37
Pagination du résultat
‰ Query setMaxResults(int n) : indique
le nombre maximum de résultats à retrouver
‰ Query setFirstResult(int n) : indique Opération de modification
la position du 1er résultat à retrouver
(numéroté à partir de 0)
en volume

R. Grin JPA page 223 R. Grin JPA page 224

Utilité Cas d’utilisation


‰ Pour les performances il est parfois mauvais ‰ Si on veut augmenter de 5% les 1000
de charger toutes les données à modifier employés de l’entreprise il serait mauvais de
dans des instances d’entités récupérer dans 1000 instances les données
‰ En ce cas, EJBQL permet de modifier les de chaque employés, de modifier le salaire
données de la base directement, sans créer de chacun, puis de sauvegarder les données
les entités correspondantes ‰ Un simple ordre SQL
update employe
set salaire = salaire * 1.05
sera énormément plus performant

R. Grin JPA page 225 R. Grin JPA page 226

Exemple Syntaxe
em.getTransaction().begin(); ‰ Les ordres de modification en volume
String ordre = référencent les classes et les propriétés des
"update Employe e " + classes mais ils ne créent aucune entité en
" set e.salaire = e.salaire * 1.05"; mémoire et ils ne mettent pas à jour les entités
Query q = em.createQuery(ordre);
déjà présentes en mémoire
int nbEntiteModifiees =
q.executeUpdate(); ‰ update Entite as alias
em.getTransaction().commit(); set alias.prop1 = val1, alias.prop2 = val2,…
where condition
‰ La condition peut être aussi complexe que la
condition d’un select

R. Grin JPA page 227 R. Grin JPA page 228

38
Remarques
‰ Les modifications doivent être faites dans une
transaction
‰ Le plus souvent il faut isoler le lancement de
ces opérations dans une transaction à part, ou
au moins exécuter ces opérations au début Exceptions
d’une transaction avant la récupération dans la
base d’entités touchées par l’opération
‰ En effet, les entités en mémoire ne sont pas
modifiées par l’opération et elles ne
correspondront alors donc plus aux nouvelles
valeurs modifiées dans la base de données
R. Grin JPA page 229 R. Grin JPA page 230

Exceptions non contrôlées Types d’exception


‰ JPA n’utilise que des exceptions non contrôlées ‰ EntityNotFoundException
(descendantes de RuntimeException) ‰ EntityExistsException
‰ JPA utilise les 2 exceptions ‰ NonUniqueResultException
IllegalArgumentException et ‰ NoResultException
IllegalStateException du paquetage
‰ TransactionRequiredException
java.lang
‰ RollbackException
‰ Sinon, toutes les autres exceptions sont dans le
paquetage javax.persistence et héritent de ‰ OptimisticLockException
PersistenceException

R. Grin JPA page 231 R. Grin JPA page 232

2 types de transactions
‰ Les transactions locales à une ressource,
fournies par JDBC sont attachées à une
seule base de données
Transaction ‰ Les transactions JTA, avec plus de
fonctionnalités que les transactions JDBC, en
particulier elles peuvent travailler avec
plusieurs bases de données

R. Grin JPA page 233 R. Grin JPA page 234

39
Transactions dans Java EE Transactions dans Java SE
(sans serveur d’applications)
‰ Elles sont étudiées dans la dernière section
de ce support de cours ‰ D’après la spécification JPA, dans Java SE,
les fournisseurs de persistance doivent
supporter les transactions locales à une
ressource, mais ne sont pas obligés de
supporter les transactions JTA
‰ La démarcation des transactions est choisie
par le développeur
‰ Les contextes de persistance peuvent couvrir
plusieurs transactions
R. Grin JPA page 235 R. Grin JPA page 236

EntityTransaction EntityTransaction

‰ En dehors d’un serveur d’applications, une public interface EntityTransaction {


application doit utiliser l’interface public void begin();
javax.persitence.EntityTransaction public void commit();
pour travailler avec des transactions locales à public void rollback();
une ressource public void setRollbackOnly();
‰ Une instance de EntityTransaction peut public boolean getRollbackOnly();
s’obtenir par la méthode getTransaction() public void isActive();
de EntityManager }

R. Grin JPA page 237 R. Grin JPA page 238

Exemple Rollback (1)


EntityManager em; ‰ En cas de rollback,
...
n rollback dans la base de données
try {
n le contexte de persistance est vidé ; toutes
em.getTransaction().begin()
les entités deviennent détachées
...
em.getTransaction().commit();
}
finally {
em.close();
}

R. Grin JPA page 239 R. Grin JPA page 240

40
Rollback (2) Transaction et contexte
de persistance
‰ Les instances d’entités Java gardent les
valeurs qu’elles avaient au moment du rollback ‰ Quand un GE n’est pas géré par un container
‰ Mais ces valeurs sont le plus souvent fausses
le contexte de persistance n’est pas fermé à
la fin d’une transaction
‰ Il est donc rare d’utiliser ces entités en les
rattachant par un merge à un GE ‰ Quand un GE est géré par un container et
que le contexte de persistance n’est pas de
‰ Le plus souvent il faut relancer des requêtes
type « étendu », le contexte est fermé à la fin
pour récupérer des entités avec des valeurs
d’une transaction (voir à la fin de ce support)
correctes

R. Grin JPA page 241 R. Grin JPA page 242

Modifications et commit Synchronisation d’un GE


avec une transaction
‰ Les modifications effectuées sur les entités
gérées sont enregistrées dans la base de ‰ Synchronisation d’un GE avec une
données au moment d’un commit transaction : le GE est enregistré auprès de la
‰ Les modifications sont enregistrées dans la transaction ; un commit de la transaction
base, même si elles ont été effectuées avant provoquera alors automatiquement un flush
le début de la transaction (avant le du GE (le GE est averti lors du commit) ; voir
tx.begin()) la dernière section de ce cours sur les
différents types de transaction

R. Grin JPA page 243 R. Grin JPA page 244

GE et threads
‰ Une fabrique de GE peut être utilisée sans
problème par plusieurs threads
‰ Mais un GE ne doit être utilisé
Concurrence concurremment que par un seul thread

R. Grin JPA page 245 R. Grin JPA page 246

41
Entités et threads Concurrence « BD »
‰ Les entités ne sont pas prévues pour être ‰ Le fournisseur de persistance peut apporter
utilisées par plusieurs threads en même temps automatiquement une aide pour éviter les
‰ Si ça doit être le cas, l’application doit prendre problèmes d’accès concurrents aux données
toutes ses précautions pour éviter les de la BD, pour les entités gérées par un GE
problèmes
‰ C’est aussi le rôle de l’application d’empêcher
qu’une entité ne soit gérée par plusieurs GE
en même temps
‰ Le rôle du fournisseur de persistance
n’intervient pas pour ces cas
R. Grin JPA page 247 R. Grin JPA page 248

Exemple de problème de Gestion de la concurrence


concurrence « BD »
‰ Par défaut, le fournisseur de persistance gère
‰ Une entité est récupérée depuis la BD (par les problèmes d’accès concurrents aux entités
un find par exemple) gérées par un GE avec une stratégie optimiste
‰ L’entité est ensuite modifiée par l’application
puis la transaction est validée
‰ Si une autre transaction a modifié entretemps
les données de la BD correspondant à
l’entité, la transaction doit être invalidée

R. Grin JPA page 249 R. Grin JPA page 250

@version Exemple
‰ Annote un attribut dont la valeur représentera
@Version
un numéro de version (incrémenté à chaque
private int version;
modification) pour l’entité et sera utilisée pour
savoir si l’état d’une entité a été modifiée entre
2 moments différents (stratégie optimiste)
‰ L’attribut doit être de type int, Integer,
short, Short, long, Long ou
java.sql.TimeStamp (si possible, éviter ce
dernier type)
‰ L’application ne doit jamais modifier un tel
attribut (modifié par JPA)
R. Grin JPA page 251 R. Grin JPA page 252

42
Entité « versionnée » lock(A, mode)
‰ C’est une entité qui possède un attribut qui ‰ Sert à protéger une entité contre les accès
possède l’annotation @version (ou le tag concurrents pour les cas où la protection
correspondant dans les fichiers XML) offerte par défaut par le fournisseur ne suffit
pas
‰ Cette entité doit être versionnée (sinon, le
traitement n’est pas portable)

R. Grin JPA page 253 R. Grin JPA page 254

Modes de blocage READ


‰ L’énumération LockModeType (paquetage ‰ Empêche les lectures non répétables sur les
javax.persistence) définit 2 modes données de la BD associées à l’entité
‰ READ : les autres transactions peuvent lire ‰ Le fournisseur de persistance peut choisir
l’entité mais ne peuvent pas la modifier une stratégie pessimiste (du type « select for
‰ WRITE : comme READ, mais en plus l’attribut update ») ou optimiste
de version est incrémenté, même si l’entité
n’a pas été modifiée (utilité expliquée dans
les transparents suivants)

R. Grin JPA page 255 R. Grin JPA page 256

READ Utilité des blocages READ


‰ Le « blocage » réel peut n’être effectué qu’au ‰ Un bilan qui calcule le total des salaires des
moment du flush ou du commit, quelle que soit employés pour chaque département doit
l’emplacement du read dans le code Java interdire qu’un employé ne change de
‰ S’il y a un problème, une exception département pendant le traitement
OptimisticLockException peut être ‰ Tous les employés peuvent être bloqués en
lancée mode READ pour éviter ce problème

R. Grin JPA page 257 R. Grin JPA page 258

43
WRITE Utilité des blocages WRITE (1)
‰ Évite en quelque sorte les problèmes de ‰ Une entête de facture contient un champ dans
lignes fantômes avec les associations qui lequel est stocké le total de la facture
concernent une entité ‰ Supposons que le calcul de ce total est
‰ En effet, le fournisseur de persistance effectué par un processus à part du processus
incrémente automatiquement le numéro de de l’ajout des lignes de la facture
version si une entité est modifiée mais pas si ‰ Lorsqu’une ligne de facture est ajoutée à une
les liens des associations qui partent de facture, l’en-tête de la facture n’est pas
l’entité sont modifiées modifiée donc le fournisseur de persistance
n’incrémente pas le numéro de version de
l’en-tête
R. Grin JPA page 259 R. Grin JPA page 260

Utilité des blocages WRITE (2) Niveau d’isolation


‰ Une ligne peut être ajoutée à une facture sans ‰ Le fournisseur suppose que le SGBD gère la
que le traitement qui calcule le total ne s’en base de données avec un niveau d’isolation
rende compte ; il y aura inconsistance entre ce « READ COMMITED » (voir cours sur les BD)
total et les lignes de la facture
‰ Si l’en-tête est bloquée en écriture pendant
l’ajout d’une ligne de facture, le traitement qui
effectue le calcul du total s’apercevra que la
facture a changé pendant le calcul puisque le
numéro de version aura été incrémenté et il
n’y aura pas inconsistance

R. Grin JPA page 261 R. Grin JPA page 262

Cas d’utilisation
‰ Le serveur d’application récupère des
données dans la BD
‰ Ces données sont montrées à l’utilisateur et
Entité détachée celui-ci peut les modifier
‰ Les modification sont repassées au serveur
et enregistrées dans la BD
‰ Les entités détachées facilitent
l’implémentation d’un tel cas d’utilisation

R. Grin JPA page 263 R. Grin JPA page 264

44
EJB 2.0 EJB 3.0
‰ Dans la norme EJB 2.0, les données de la BD ‰ Plus ce problème dans la norme EJB 3.0
étaient enregistrées dans un objet EJB entité ‰ Les entités peuvent être détachées de leur
‰ Le problème était qu’un objet entité ne contexte de persistance d’origine et
pouvait exister que dans l’environnement du rattachées par la suite
serveur d’application
‰ Les données était donc souvent passées au
client sous forme de DTO (pour éviter de
nombreux appels distants aux EJB entités,
qui sont coûteux)

R. Grin JPA page 265 R. Grin JPA page 266

EJB 3.0 Rattachement


‰ Une fois détachées les entités peuvent être ‰ La méthode merge de EntityManager
passées sans problème à la couche cliente permet d’obtenir une entité gérée à partir
‰ Les modifications effectuées par l’utilisateur d’une entité détachée
peuvent être enregistrées dans l’entité ‰ Sa signature :
détachée <T> T merge(T entité)
‰ L’entité peut ensuite être rattachée à un GE ‰ Attention, l’entité passée en paramètre n’est
et les modifications sont alors enregistrées pas rattachée ; c’est l’entité renvoyée par la
dans la base de données méthode merge qui est rattachée ; cette
entité a le même état et la même clé primaire
que l’entité passée en paramètre
R. Grin JPA page 267 R. Grin JPA page 268

Exemples de détachement État d’une entité détachée


‰ Un servlet peut décider d’enregistrer des ‰ Une entité détachée continue à exister mais
entités dans une session d’utilisateur ; cette la synchronisation avec la BD n’est pas
session peut être sérialisée par un conteneur garantie
de servlet (et les entités sont alors ‰ L’état d’une entité détachée peut ne pas être
détachées) entièrement disponible
‰ Une application peut éviter l’utilisation de
DTO en transférant les données entre les
clients et le serveur dans des objets
détachés, évitant ainsi des recopies inutiles

R. Grin JPA page 269 R. Grin JPA page 270

45
État d’une entité État d’une entité
‰ En effet, pour des raisons de performances, ‰ Un attribut persistant d’une entité est
une entité gérée par un GE (attachée) peut ne immédiatement disponible dans les 2 cas
récupérer dans la BD qu’une partie de son état suivants :
‰ Le reste de l’état ne sera récupéré que lorsque n l’attribut a déjà été utilisé
l’entité en aura vraiment besoin, avec l’aide du n l’attribut n’a pas été marqué par
GE fetch=LAZY
‰ Si l’entité est détachée alors qu’une partie de
son état n’a pas encore été récupérée, la
partie manquante de l’entité détachée ne sera
pas disponible
R. Grin JPA page 271 R. Grin JPA page 272

État d’une entité détachée Mode de récupération


des associations
‰ Une entité peut donc ne pas être totalement
initialisée au moment de son détachement ‰ Si une association d’un objet détaché a le
mode de récupération LAZY, il n’est possible
‰ Par exemple, si une association d’une entité
détachée a l’attribut fetch=LAZY, il est de naviguer à travers cette association que si
possible que l’association ne puisse être n l’application a déjà effectué cette

récupérée (dépend des circonstances et des navigation


fournisseurs de JPA) n ou si l’association a été chargée par un

‰ En ce cas, une fois détachée et loin du GE, la join fetch lors d’une requête
norme n’assure pas que l’entité puisse
récupérer l’état manquant
R. Grin JPA page 273 R. Grin JPA page 274

Rendre accessible l’état Récupérer une association avant


d’une entité détachée le détachement
‰ 2 solutions pour accéder à tout l’état d’une ‰ Si le but est une entité (OneToOne ou
entité détachée ManyToOne), il suffit de lire une des
‰ L’application récupère tout l’état de l’entité propriétés de l’entité
gérée avant le détachement ‰ Si le but est une collection (OneToMany ou
‰ L’application rattache l’entité par la méthode ManyToMany), l’appel de la méthode size()
merge pour récupérer l’état manquant de la collection suffit le plus souvent

R. Grin JPA page 275 R. Grin JPA page 276

46
Entité détachée et concurrence Conflit de concurrence
‰ Avant que les modifications sur l’entité ‰ Si les données de la BD associée à un objet
détachée ne soient enregistrées dans la BD, détaché ont été modifiées depuis le
l’entité doit être rattachée à un contexte de détachement de l’objet, merge lance une
persistance (celui d’origine ou un autre) exception, ou le commit échouera
‰ A ce moment, ou au moment du commit qui ‰ Tout se passe donc comme si un conflit de
enregistre vraiment les modifications, le concurrence avait été détecté (avec une
contexte de persistance vérifie qu’il n’y a pas stratégie optimiste)
de conflit de concurrence

R. Grin JPA page 277 R. Grin JPA page 278

Détachement automatique Associations


‰ Quelques situations provoquent un ‰ X entité détachée ; association entre X et Y
détachement automatique des entités gérées : ‰ L’état de Y peut être « disponible » dans ces
n Après un commit si le contexte de cas :
persistance est limité à la transaction (avec n Y a été retrouvé par find
un serveur d’applications) n Y a été retrouvée par une requête avec une
n Après un rollback clause join fetch
n Après un clear du GE n une propriété de Y non clé primaire a déjà
n Après la fermeture du GE été accédée par l’application
n Après le passage par valeur de l’entité avec n Y est navigable depuis une entité disponible
une méthode « remote » avec l’association marquée fetch=EAGER
R. Grin JPA page 279 R. Grin JPA page 280

‰ Les performances d’une application peuvent


être grandement améliorées par
n un choix adapté du mode de récupération
Optimisations des entités associées
n l’utilisation d’opérations de modifications
de grandes quantités de données sans
création d’entités

R. Grin JPA page 281 R. Grin JPA page 282

47
Méthodes « callback »
‰ Des méthodes peuvent être annotées pour
indiquer qu’elles seront appelées par le
fournisseur de persistance quand une entité
Callback passera dans une nouvelle étape de son
cycle de vie
‰ Ces méthodes peuvent appartenir à une
classe entité (entity ou classe mère
« mapped ») ou à une classe « écouteur »

R. Grin JPA page 283 R. Grin JPA page 284

Types de méthode Fichier XML


‰ @PrePersist : quand persist (ou merge) s’est ‰ Les méthodes callback peuvent aussi être
terminé avec succès indiquées dans un fichier XML
‰ @PostPersist : après l’insertion dans la BD ‰ Un fichier XML peut indiquer des méthodes
‰ @PreRemove : quand remove est appelé callback par défaut qui seront appelées pour
‰ @PostRemove : après suppression dans la BD toutes les entités
‰ @PreUpdate : avant modification dans la BD
‰ @PostUpdate : après modification dans la BD
‰ @PostLoad : après la lecture des données de
la BD pour construire une entité

R. Grin JPA page 285 R. Grin JPA page 286

Configuration d’une unité de


persistance
‰ Dans un environnent non géré par un serveur
d’applications, il est nécessaire de donner les
Configuration d’une unité de informations pour la connexion à la base de
persistance données
‰ Ces informations, ainsi que d’autres
informations, comme les noms des classes
entités, doivent être données dans un fichier
persistence.xml situé dans un sous-
répertoire META-INF d’un des répertoires du
classpath
R. Grin JPA page 287 R. Grin JPA page 288

48
Configuration d’une unité de persistence.xml
persistance <persistence
xmlns="http://java.sun.com/xml/ns/persistence"
‰ Les informations indiquent comment se version= "1.0" >
connecter à la base de données, ainsi que <persistence-unit name="Employes"
d’autres informations, comme les noms des transaction-type="RESOURCE_LOCAL">
classes entités, la configuration de <class>p1.Employe</class>
l’environnement de mis au point (logging, <class>p1.Dept</class>
affichage des ordres SQL lancés dans le <properties>
SGBD,…) ou des propriétés particulières au . . . <!– Voir transparent suivant-->
driver du fournisseur de persistance </properties>
</persistence-unit>
</persistence>
R. Grin JPA page 289 R. Grin JPA page 290

Section properties Exemple de section properties


‰ La section properties dépend du <properties>
<property
fournisseur des fonctionnalités décrites dans name="toplink.jdbc.driver"
la spécification JPA value="oracle.jdbc.OracleDriver"/>
‰ Elle contient les informations pour la <property
connexion mais aussi d’autres informations name="toplink.jdbc.url"
value="jdbc:oracle:thin:@...:INFO "/>
pour le logging ou la création automatique
<property name="toplink.jdbc.user"
des tables si elle n’existent pas déjà ; il faut value="toto"/>
consulter la documentation du fournisseur <property name="toplink.jdbc.password"
value="mdp"/>
</properties>

R. Grin JPA page 291 R. Grin JPA page 292

Les ajouts de TopLink Génération automatique des tables


‰ La propriété toplink.ddl-generation
‰ TopLink a des extensions par rapport à la
permet de créer automatiquement les tables
norme JPA
au moment de l’exécution
‰ Par exemple,
‰ Cette propriété peut avoir 3 valeurs :
n logging
n none : aucune création automatique
n génération automatique de tables
n create-tables : les tables sont créées
n…
si elles n’existent pas déjà
n drop-and-create-tables : si une table

existe déjà, elle est d’abord supprimée


avant d’être recréée (utile pour les tests)
R. Grin JPA page 293 R. Grin JPA page 294

49
Exemple
<properties> ‰ toplink.ddl-generation.output-mode
. . . indique ce qui sera fait avec les fichiers DDL
<property name="toplink.ddl-generation" ‰ Valeurs possibles :
value="drop-and-create-tables"/>
n sql-script génère les fichiers mais ne
</properties>
les exécute pas
n database exécute les ordres DDL mais

ne génère pas les fichiers


n both génère les fichiers et les exécute

(valeur par défaut)

R. Grin JPA page 295 R. Grin JPA page 296

‰ Propriété toplink.application- ‰ toplink.create-ddl-jdbc-file-name


location indique le nom du répertoire qui indique le nom du fichier qui contiendra les
contiendra les fichiers contenant les ordres ordres de création des tables ; par défaut,
DDL de création et de suppression des tables createDDL.jdbc
(le répertoire courant par défaut) ‰ toplink.drop-ddl-jdbc-file-name
idem pour la suppression des tables ; par
défaut, dropDDL.jdbc

R. Grin JPA page 297 R. Grin JPA page 298

logging (1) logging (2)


‰ La propriété toplink.logging.level n FINE : donne des informations sur les ordres
peut avoir les valeurs SQL utile pendant les tests et la mise au point
n OFF : aucune information n FINER : encore plus d’informations, par exemple
sur les transactions
n SEVERE : uniquement les erreurs
n FINEST : encore plus d’informations, par
n WARNING : les avertissements (et les erreurs)
exemple sur l’utilisation des séquences
n INFO (valeur par défaut) : assez peu
d’information en plus
n CONFIG : donne des informations au moment du
déploiement sur la configuration

R. Grin JPA page 299 R. Grin JPA page 300

50
Placement des fichiers XML
‰ Par défaut les fichiers XML contenant les
méta données sont placées dans le fichier
META-INF/orm.xml, sous un répertoire du
Fichiers XML classpath
‰ Il est possible d’indiquer d’autres
emplacements avec le tag <mapping-file>
dans le fichier persistence.xml qui définit
l’unité de persistance

R. Grin JPA page 301 R. Grin JPA page 302

Exemple Fichiers XML – annotations


‰ Avantages des annotations :
<persistence-unit name="xxxx">
n méta données proches du code
...
<mapping-file>META-INF/queries.xml n pas besoin de donner le contexte comme

</mapping-file> dans les fichiers XML


<mapping-file>META-INF/entities.xml n plus simple

</mapping-file> ‰ Inconvénients :
</persistence-unit> n changement des méta données nécessite
une recompilation
‰ Les informations données dans les fichiers
XML l’emportent sur les annotations
R. Grin JPA page 303 R. Grin JPA page 304

Fichiers XML – annotations


‰ Les annotations sont le plus souvent utilisées ‰ La fin de ce support concerne les serveurs
‰ Les fichiers de configuration XML peuvent être d’application et n’est donnée qu’à titre de
préférés lorsque l’information référence pour ceux qui utiliseront un tel
n est dépendante de l’environnement serveur
d’exécution ; par exemple pour les noms de ‰ Le contenu ne fait pas partie du programme
tables ou de colonnes demandé à l’examen
n concerne plusieurs classes ; par exemple
@TableGenerator qui donne le nom de la
table qui génère automatiquement les clés
d’identification des entités
R. Grin JPA page 305 R. Grin JPA page 306

51
JPA dans les serveurs
Types de gestionnaires d’entités
d’applications

R. Grin JPA page 307 R. Grin JPA page 308

Types de GE (1) Types de GE (2)


‰ GE géré par le container (uniquement ‰ Un GE géré par le container peut être d'un des
disponible dans un serveur d’applications) 2 types suivants :
‰ GE géré par l’application (seul type disponible n délimité par les transactions
en dehors d’un serveur d’applications) ; pas (TRANSACTION ; c'est le type par défaut)
délimité par les transactions n peut survivre à une fin de transaction
(EXTENDED) ; nécessite un bean session
avec état (stateful)

R. Grin JPA page 309 R. Grin JPA page 310

GE géré par le container GE géré par le container (2)


‰ Le contexte de persistance est injecté par le ‰ Il est possible de faire durer un contexte de
serveur d’application : persistance pendant plusieurs transactions
@PersistenceContext(unitName="Xxxxx")
‰ Pour cela il faut créer un contexte de
‰ Avec un serveur d’applications, par défaut la persistance étendu :
durée de vie d’un contexte de persistance est @PersistenceContext(unitName="Xxxxx"
la transaction : il est fermé quand la type=PersistenceContextType=EXTENDED)
transaction se termine ‰ Ce type de GE n’est disponible que dans un
bean session avec état (stateful) ; il n’est pas
disponible dans un bean session sans état
(stateless)
R. Grin JPA page 311 R. Grin JPA page 312

52
GE géré par le container (3) Contexte de persistance de
portée limitée à une transaction
‰ L’application peut gérer elle-même la création ‰ Dans le cas d’un contexte de persistance de
d’un GE en utilisant une fabrique de GE portée limitée à une transaction (pas le cas si
(méthode createEntityManager()) application en dehors d’un container),
‰ La fabrique de gestionnaires d’entités n persist, merge, remove et refresh

s’obtient par injection de ressource (fournie doivent être invoquées dans le contexte
par le serveur d’applications) : d’une transaction
@PersistenceUnit n find et getReference (comme les

EntityManagerFactory emf; résultats de l’exécution d’un Query)


peuvent être invoqués en dehors du
contexte d’une transaction mais dans ce
cas les entités renvoyées sont détachées
R. Grin JPA page 313 R. Grin JPA page 314

Transactions
‰ Une requête peut être lancée en dehors de
toute transaction
‰ Dans le cas où le contexte de persistance est
limité à une transaction, les entités seront Types de transactions
détachées (non gérées par un GE)

R. Grin JPA page 315 R. Grin JPA page 316

Transactions disponibles dans Java EE Démarcation des transactions


dans Java EE
‰ Les serveurs d’applications utilisent par
‰ Transactions JTA gérées par le serveur
défaut les transactions JTA, mais les
transactions locales à une ressource (celles d’application : les transactions sont démarrées
qui utilisent l'API de JDBC pour les (ou non) au début d’une méthode et terminées
(ou non) à la fin d’une méthode, suivant les
transactions) sont aussi disponibles
indications données par le développeur par
‰ Les transactions sont gérées par le container
annotation ou dans un fichier XML
du serveur d’application ou par l’application
‰ Transactions gérées par l’application :
‰ Seules les transactions JTA peuvent être
l’application décide de démarrer et de terminer
gérées par le container une transaction n’importe où dans le code

R. Grin JPA page 317 R. Grin JPA page 318

53
Transactions gérées par l’application Environnement par défaut
disponibles dans Java EE dans un serveur d’applications
‰ Le code utilise l’interface ‰ Contexte de persistance géré par le container
javax.transaction.UserTransaction (injecté par annotation ou par lookup JNDI)
qui possède des méthodes pour démarrer, ‰ Contexte de persistance limité à une seule
terminer ou marquer pour invalidation une transaction
transaction JTA
‰ Transaction JTA dont les démarcations sont
‰ Une instance de UserTransaction peut
fixées déclarativement (par annotation ou
être injectée par une annotation @Resource
dans un fichier XML)

R. Grin JPA page 319 R. Grin JPA page 320

Un principe Modèle de conception dans Java EE


‰ La configuration par défaut correspond au
‰ Pour que tout se passe bien, tous les appels
modèle de conception « une transaction par
de méthodes des GE durant une même
requête de l’utilisateur » :
transaction doivent utiliser le même contexte
de persistance n la transaction démarre au début du
traitement d’une requête
‰ Sinon, des modifications effectuées sur des
entités durant la transaction risquent d’être n et elle se termine à la fin du traitement

perdues par la suite dans la transaction ‰ Pour faciliter l’utilisation de ce modèle, le


‰ JPA facilite l'application de ce principe (voir contexte de persistance peut se propager aux
transparent suivant) méthodes appelées durant toute la durée
d’une transaction (détaillé plus loin)
R. Grin JPA page 321 R. Grin JPA page 322

Autre modèle de conception Propagation de contexte


‰ Pour faciliter la tâche du développeur, les
‰ Avec un bean session avec état (stateful) il transactions JTA permettent la propagation
est possible d’utiliser un même contexte de de contexte pour les GE gérés par le
persistance étendue pour plusieurs container
transactions JTA
‰ Cette propagation de contexte peut
‰ Le modèle de conception correspond à des occasionner des collisions de contexte dans
traitements « conversationnels » qui peuvent certaines situations dans lesquelles des
couvrir plusieurs requêtes de l’utilisateur beans sessions avec état sont impliqués
‰ L’héritage de contexte limite les possibilités
de conflit
R. Grin JPA page 323 R. Grin JPA page 324

54
Définition Définition
‰ Un contexte de persistance peut être propagé
‰ Association d’un contexte de persistance
durant une transaction JTA s’il est utilisé par
avec une transaction JTA : le contexte de
des GEs gérés par le container
persistance est lié à la transaction ; le
contexte devient le contexte actif lié à la ‰ Ce contexte est alors utilisé à tour de rôle
transaction durant la transaction par les GEs
‰ Cette association va permettre au container ‰ Cette propagation s’appelle une propagation
de retrouver un contexte de persistance en de contexte
interrogeant la transaction, et donc de ‰ Quand un GE reçoit un message, il vérifie s’il
permettre la propagation de contexte existe un contexte propagé ; si c’est le cas, il
utilise celui-ci, sinon il en crée un nouveau
R. Grin JPA page 325 R. Grin JPA page 326

Avantage de la propagation Conflit de contextes


‰ La propagation de contexte ne fonctionne pas
‰ Les modifications non encore enregistrées
lors de l’appel d’une méthode d’un bean
dans la base (elles le seront seulement au
session avec état (stateful) depuis un autre
commit de la transaction), mais enregistrées
bean
dans le contexte de persistance, sont
disponibles durant toute la transaction, quel ‰ En effet, une bean session avec état ne peut
que soit l’emplacement du code placé dans la travailler qu’avec un seul contexte et ne peut
transaction accepter de travailler avec un autre contexte
propagé
‰ Une exception est levée
‰ Voir la spécification JPA pour plus de détails

R. Grin JPA page 327 R. Grin JPA page 328

Héritage de contexte Synchronisation


‰ Une exception pour la collision de contexte : ‰ Il est possible de synchroniser plusieurs
un bean avec état créé par un autre bean contextes de persistance gérés par
avec état hérite du contexte de ce bean si les l’application avec une même transaction JTA
2 beans utilisent un contexte de persistance ‰ Mais un seul contexte géré par le container
étendu peut être synchronisé avec une transaction
‰ Ainsi des appels de méthodes pourront se JTA
faire entre les 2 beans sans collision de
contexte

R. Grin JPA page 329 R. Grin JPA page 330

55
Conversation longue (1) Conversation longue (2)
‰ L'utilisation d'un contexte étendu permet ‰ On peut commencer par une transaction,
d'implémenter des conversations longues valider la transaction, passer des données au
entre un client et un bean session avec état client qui les modifie et ensuite reprendre une
‰ Il n'est pas indispensable, et souvent néfaste, autre transaction pour terminer la conversation
qu'une seule transaction longue couvre toute ‰ Dès que la 2ème transaction démarre, toutes
la conversation les modifications faites entre les 2 transactions
sont prises en compte par cette 2ème
transaction

R. Grin JPA page 331 R. Grin JPA page 332

joinTransaction

‰ Lorsqu’un GE est créé explicitement par


l’application (il n’est pas géré par le
container), 2 cas :
n si une transaction JTA est déjà active, le Bibliographie
contexte du GE est synchronisé avec la
transaction
n sinon le contexte peut manuellement être
synchronisé avec la transaction par la
méthode joinTransaction() de
EntityManager
R. Grin JPA page 333 R. Grin JPA page 334

Sites Web (1) Sites Web (2)


‰ Spécification officielle de JPA : ‰ Hibernate :
http://jcp.org/aboutJava/communityprocess/final http://www.hibernate.org/hib_docs/entitymanag
/jsr220/index.html (cliquer sur le 1er bouton er/reference/en/html/
« download the Specification for evaluation or to ‰ Kodo :
build an application that uses the Specification » http://e-
‰ Toplink : docs.bea.com/kodo/docs40/full/html/ejb3_overvi
http://www.oracle.com/technology/products/ias/t ew.html
oplink/jpa/index.html

R. Grin JPA page 335 R. Grin JPA page 336

56
Livre
‰ Pro EJB 3 – JPA
de Mike Keith et Merrick Schincariol
Edition Apress
(en anglais)

R. Grin JPA page 337

57

Vous aimerez peut-être aussi