Vous êtes sur la page 1sur 49

Plan de la partie 2 (1/2)

(Java Persistence API) - Partie 2


Universit de Nice - Sophia Antipolis
Version 2.15 1/2/12 Richard Grin

JPA 2.0

Rcuprer des donnes de la base Langage dinterrogation JPQL API Critre Modifications en volume Exceptions Transaction Concurrence Entits dtaches Configuration dune unit de persistance

R. Grin JPA page 2

Plan de la partie 2 (2/2)


Fichiers de configuration XML JPA et DAOs Cache des donnes Optimisation Mthodes callbacks et couteurs Validation Adaptation une base de donnes prexistante Prcisions pour la gnration du schma de la base de donnes

R. Grin JPA page 3 R. Grin

Rcuprer des donnes de la base de donnes

JPA

page 4

Rappel important

Cette section montre comment interroger la base de donnes pour rcuprer des entits (des employs par exemple) ou des simples valeurs (des noms demploys ou le total des salaires des employs par exemple)

Toutes les entits retrouves par find, getReference ou un query sont automatiquement gres par le gestionnaire dentits Les modifications apportes ces entits sont donc enregistres au prochain commit (mais les nouveaux objets associs lentit retrouve ne sont pas automatiquement persistants mme s'il y a une cascade sur persist ; a ne marche que pour un appel explicite de la mthode persist)

R. Grin JPA page 6

R. Grin

JPA

page 5

Chercher par identit


find et getReference (de EntityManager) permettent de retrouver une entit en donnant son identificateur dans la BD <T> T find(Class<T> classeEntit, Object clPrimaire) <T> T getReference(Class<T> classeEntit, Object clPrimaire) Le rsultat est null si aucune entit na cet identificateur dans la base de donne

R. Grin JPA page 7

Exemple
Departement dept = em.find(Departement.class, 10);

R. Grin

JPA

page 8

getReference
getReference renvoie une rfrence vers une entit, sans que cette entit ne soit ncessairement initialise Le plus souvent il vaut mieux utiliser find

getReference
getReference peut tre (rarement) utilise pour amliorer les performances quand une entit non initialise peut tre suffisante, sans que lentit entire soit retrouve dans la base de donnes Par exemple, pour indiquer une association dont le but est unique (OneToOne ou ManyToOne) :
Departement dept = em.getReference(Departement.class, 10); Employe emp.setDepartement(dept);

R. Grin

JPA

page 9

R. Grin

JPA

page 10

Interroger la base de donnes


tapes pour rcuprer des donnes


1. 2. 3. 4.

Il est possible de rechercher des donnes sur des critres plus complexes que la simple identit Remarque : dans toute la partie venir sur les requtes (query, JPQL, API criteria), entit peut dsigner une entit ou une classe (ou instance de) Embeddable ; depuis JPA 2.0, les classes Embeddable ont les mmes droits que les classes entits

Dcrire ce qui est recherch (langage JPQL ou criteria API) Crer une instance de type Query Initialiser la requte (paramtres, pagination) Lancer lexcution de la requte

R. Grin

JPA

page 11

R. Grin

JPA

page 12

Exemple
String s = "select e from Employe as e"; Query query = em.createQuery(s); List<Employe> listeEmployes = (List<Employe>)query.getResultList();

Exemple plus complexe


String q = "select e from Employe as e " + "where e.departement.numero = :numero"; Query query = em.createQuery(q); query.setParameter("numero", 10); query.setMaxResults(30); for (int i = 0; i < 5; i++) { query.setFirstResult(30 * i); List<Employe> listeEmployes = (List<Employe>)query.getResultList(); ... // Affichage page numro i + 1 }
R. Grin JPA page 14

R. Grin

JPA

page 13

Description de la requte
Le langage JPQL (Java Persistence Query Language) permet de dcrire ce que lapplication recherche (voir prochaine section) Il ressemble beaucoup SQL :

Requtes sur les entits objet


Les requtes JPQL ou criteria travaillent avec le modle objet et pas avec le modle relationnel Les identificateurs dsignent les entits et leurs attributs et pas les tables et leurs colonnes Les seules classes qui peuvent tre explicitement dsignes (par leur nom) dans une requte sont les entits et les classes Embeddable Rappel : le nom est donn par lattribut @name de @Entity ou @Embeddable, ou, par dfaut, par le nom de la classe

R. Grin JPA page 16

select e from Employe e where e.nom = 'Dupond'


LAPI Criteria a t introduite par JPA 2.0 pour dcrire la requte dune faon plus sre, vrifie la compilation (tudie la suite de JPQL)
JPA page 15

R. Grin

Type du rsultat

Query
Pour faire excuter la requte il faut crer un Query, instance qui reprsente une requte (tudie en dtails un peu plus loin) Plusieurs mthodes de EntityManager permettent dobtenir un Query, suivant la faon dont la requte a t dcrite

Lexpression renvoye peut tre n une (ou plusieurs) expression entit , par exemple un employ (e par exemple)
n

une (ou plusieurs) expression valeur , par exemple le nom dun employ (e.nom), y compris une expression arithmtique (e.salaire * 1.25) Lexpression ne peut pas tre une collection (d.employes par exemple), bien que certains fournisseurs de persistance le permettent !
R. Grin JPA page 17

R. Grin

JPA

page 18

Mthodes pour obtenir un Query


Les mthodes suivantes de EntityManager renvoient un Query ; elles sont lies au langage JPQL, lAPI criteria , aux requtes natives SQL et aux requtes nommes (tout cela sera tudi dans la suite du cours) createQuery(String jpql) createQuery(CriteriaQuery criteria) createNativeQuery(String sql) createNamedQuery(String nom)

R. Grin JPA page 19

Excuter une requte (1)


Plusieurs mthodes de linterface Query permettent dexcuter une requte et de rcuprer son rsultat

R. Grin

JPA

page 20

Excuter une requte (2)


Excuter une requte (3)


Pour le cas o une seule valeur ou entit est renvoye, le plus simple est dutiliser la mthode getSingleResult() ; elle renvoie un Object La mthode lance des exceptions sil ny a pas exactement une entit qui correspond la requte : n NoResultException n NonUniqueResultException
JPA page 21

Si plusieurs valeurs ou entits peuvent tre renvoyes, il faut utiliser la mthode getResultList() de linterface Query

Elle renvoie une liste raw (pas gnrique) des rsultats, instance de java.util.List, ventuellement vide si le rsultat est vide Un message davertissement est affich durant la compilation si le rsultat est rang dans une liste gnrique (List<Employe> par exemple)

R. Grin JPA page 22

R. Grin

Type dun lment du rsultat


Exemple 1 : renvoie une entit


String s = "select e from Employe as e"; Query query = em.createQuery(s); List<Employe> listeEmployes = (List<Employe>)query.getResultList();

Le type dun lment de la liste (ou de lunique valeur ou entit renvoye) est n Object si la clause select ne comporte quune seule expression n Object[] si elle comporte plusieurs expressions

On peut faire un cast

R. Grin

JPA

page 23

R. Grin

JPA

page 24

Exemple 2 : renvoie une proprit


String s = "select e.nom from Employe as e"; Query query = em.createQuery(s); List<String> listeEmployes = (List<String>)query.getResultList();

Exemple 3 : renvoie plusieurs valeurs


texte = "select e.nom, e.salaire " + " from Employe as e"; query = em.createQuery(texte); List<Object[]> liste = (List<Object[]>)query.getResultList(); for (Object[] info : liste) { System.out.println(info[0] + " gagne " + info[1]); }

On peut faire un cast

R. Grin

JPA

page 25

R. Grin

JPA

page 26

Mthodes de Query (1)


Mthodes de Query (2)


List getResultList() Object getSingleResult() int executeUpdate() Query setMaxResults(int nbResultats) Query setFirstResult(int positionDepart) Query setFlushMode(FlushModeType modeFlush)
R. Grin JPA page 27

Query setParameter(String nom, Object valeur) Query setParameter(String nom, Date valeur, TemporalType typeTemporel) Query setParameter(String nom, Calendar valeur, TemporalType typeTemporel)

R. Grin

JPA

page 28

Types temporels

Exemple

On a vu que les 2 types java temporels du paquetage java.util (Date et Calendar) ncessitent une annotation @Temporal Ils ncessitent aussi un paramtre supplmentaire pour la mthode setParameter

@Temporal(TemporalType.DATE) private Calendar dateEmb; em.createQuery("select e from employe e" + " where e.dateEmb between ?1 and ?2") .setParameter(1, debut, TemporalType.DATE) .setParameter(2, fin, TemporalType.DATE) .getResultList();

R. Grin

JPA

page 29

R. Grin

JPA

page 30

Types de requte

Paramtres des requtes


Requte dynamique dont le texte JPQL est donn en paramtre de createQuery Requte native (ou requte SQL) particulire un SGBD ou trop complexe pour JPA ; requte SQL (pas JPQL) avec tables et colonnes (pas classes et attributs) ; createNativeQuery Requte nomme dont le texte est donn statiquement dans une annotation dune entit et dont le nom est pass en paramtre de createNamedQuery ; une requte nomme peut tre crite en JPQL ou en SQL (native)
JPA page 31

Un paramtre peut tre dsign par son numro (?n) ou par son nom (:nom) Les valeurs des paramtres sont donnes par les mthodes setParameter

Les paramtres sont numrots partir de 1 Un paramtre peut tre utilis plus dune fois dans une requte Lusage des paramtres nomms est recommand (plus lisible)
R. Grin JPA page 32

R. Grin

Requte nomme (1)


Seules les entits peuvent contenir des dfinitions de requtes nommes Une requte nomme peut tre mise dans nimporte quelle entit, mais on choisira le plus souvent lentit qui correspond ce qui est renvoy par la requte Le nom de la requte nomme doit tre unique parmi toutes les entits de lunit de persistance ; on pourra, par exemple, prfixer le nom par le nom de lentit : Employe.findAll

R. Grin JPA page 33

Requte nomme (2)


Les requtes nommes peuvent tre analyse et prcompiles par le fournisseur de persistance au dmarrage de lapplication, ce qui peut amliorer les performances Lannotation @NamedQuery dfinit une requte nomme crite en JPQL Lannotation @NamedNativeQuery dfinit une requte nomme crite en SQL (native)

R. Grin

JPA

page 34

Exemple de requte nomme


@Entity @NamedQuery ( name="findNomsEmployes", query="select e.nom from Employe as e where upper(e.departement.nom) = :nomDept" ) public class Employe extends Personne { ... Query q = em.createNamedQuery("findNomsEmployes");
R. Grin JPA page 35 R. Grin

Exemples

Query query = em.createQuery( "select e from Employe as e " + "where e.nom = ?1"); query.setParameter(1, "Dupond"); Query query = em.createQuery( "select e from Employe as e " + "where e.nom = :nom"); query.setParameter("nom", "Dupond");

JPA

page 36

Plusieurs requtes nommes


Mapping pour requtes natives (1)


Il est ncessaire de donner des informations sur les colonnes renvoyes par la requte SQL afin que le gestionnaire dentits sache si elle correspondent des entits Dans le cas o toutes les colonnes correspondent aux attributs dune entit ces informations de mapping sont indiques en donnant la classe de lentit en paramtre de createNativeQuery

Si une classe a plusieurs requtes nommes, il faut les regrouper dans une annotation @NamedQueries :
@NamedQueries({ @NamedQuery(...), @NamedQuery(...), ... })

R. Grin

JPA

page 37

R. Grin

JPA

page 38

Exemple
String requete = "select matr, nome,, dept " SQL Oracle + " from emp " (connect by) + " start with matr = ?1 " + " connect by prior matr = sup "; List<Employe> employes = (List<Employe>) em.createNativeQuery(requete, Employe.class) .setParameter(1, idChef); .getResultList();
R. Grin JPA page 39

Mapping pour requtes natives (2)


Dans les autres cas, une annotation @SqlResultSetMapping est ncessaire Elle doit tre ajoute une entit quelconque Cette annotation a un nom qui doit tre pass en paramtre la mthode createNativeQuery Consultez une documentation sur JPA pour en savoir plus

R. Grin

JPA

page 40

Requtes natives ou JDBC ?


Mode de flush
Normalement (mode FlushMode.AUTO) un flush des entits concernes par une requte est effectu avant la requte pour que le rsultat tienne compte des modifications effectues en mmoire sur ces entits Pour une requte il est possible d'viter ce flush avec la mthode setFlushMode :
query.setFlushMode(FlushMode.COMMIT);

Si une entit est renvoye par la requte, il vaut mieux utiliser une requte native car le gestionnaire dentits grera lentit comme les autres entits et le code est plus simple Si des valeurs scalaires sont renvoyes, le choix est moins clair ; utiliser une requte nomme permettra de rester dans JPA Rarement, une requte trop complexe imposera JDBC

R. Grin JPA page 41

Dans ce mode, seul un commit provoquera un flush


R. Grin JPA page 42

Pagination du rsultat
Query setMaxResults(int n) : indique le nombre maximum de rsultats retrouver Query setFirstResult(int n) : indique la position du 1er rsultat retrouver (numrot partir de 0)

Enchanement des mthodes


Les mthodes setParameter, setMaxResults renvoient le Query modifi On peut donc les enchaner Exemple :
em.createQuery(texteQuery) .setParameter(nomParam, valeurParam) .setFirstResult(30 * i) .setMaxResults(30) .getResultList();

R. Grin

JPA

page 43

R. Grin

JPA

page 44

Exemples de requtes JPQL


Langage JPQL Java Persistence Query Language

select e from Employe as e select e.nom, e.salaire from Employe e select e from Employe e where e.departement.nom = 'Direction' select d.nom, avg(e.salaire) from Departement d join d.employes e group by d.nom having count(d.nom) > 5

R. Grin

JPA

page 45

R. Grin

JPA

page 46

Alias
Le texte des requtes utilise les alias de classe : select e from Employe as e Les attributs des classes doivent tre prfixs par les alias : e.nom Une erreur frquente du dbutant est doublier les alias en prfixe

Clauses dun select


select : type des objets ou valeurs renvoyes from : o les donnes sont rcupres where : slectionne les donnes group by : regroupe des donnes having : slectionne les groupes (ne peut exister sans clause group by) order by : ordonne les donnes

R. Grin

JPA

page 47

R. Grin

JPA

page 48

Polymorphisme dans les requtes (1)


Les mots-cls select, from, distinct, join, sont insensibles la casse

Toutes les requtes sont polymorphes : un nom de classe dans la clause from dsigne cette classe et toutes les sous-classes Exemple : select count(a) from Article as a compte le nombre dinstances de la classe Article et de tous les sous-classes de Article

Depuis JPA 2 on peut restreindre un type donn : select a from Article where type(a)
JPA page 50

R. Grin

JPA

page 49

R. Grin

Polymorphisme dans les requtes (2)


Expression de chemin

Depuis JPA 2 on peut restreindre un type donn : select a from Article a where type(a) in (Stylo, Lot)

Les requtes peuvent contenir des expressions de chemin pour naviguer entre les entits en suivant les associations dclares dans le modle objet (les annotations @OneToOne, @OneToMany, ) La notation pointe est utilise

R. Grin

JPA

page 51

R. Grin

JPA

page 52

Rgle pour les expressions de chemin


Exemples

Une navigation peut tre chane une navigation prcdente la condition que la navigation prcdente ne donne quune seule entit (OneToOne ou ManyToOne) Dans le cas o une navigation aboutit plusieurs entits, il est possible dutiliser la clause join tudie plus loin pour obtenir ces entits
JPA page 53

Si e est un alias pour Employe, n e.departement dsigne le dpartement dun employ n e.projets dsigne la collection de projets auxquels participe un employ
select e.nom from Employe as e where e.departement.nom = 'Qualit'

e.projets.nom nest pas autoris car e.projets est une collection (voir clause join)
JPA page 54

R. Grin

R. Grin

Autre exemple
select e.nom, e.departement.nom, e.superieur.departement.nom from Employe e

distinct
Dans une clause select, indique que les valeurs dupliques sont limines (la requte ne garde quune seule des valeurs gales) Exemple : select distinct e.departement from Employe e

R. Grin

JPA

page 55

R. Grin

JPA

page 56

new
Il est possible de renvoyer des instances dune classe dont le constructeur prend en paramtre des informations rcupres dans la base de donnes La classe doit tre dsigne par son nom complet (avec le nom du paquetage) Exemple :

Group by
On peut regrouper sur un alias ou sur attribut ; on regroupe ici sur un alias : select d, count(e) from Departement d join d.employes e group by d Les expressions du select (ou du order by sil y en a un) qui ne sont pas des regroupements doivent se trouver aussi dans le group by, ce qui peut amener ajouter une expression inutile dans le group by
JPA page 58

select new p1.p2.Classe(e.nom, e.salaire) from Employe e

R. Grin

JPA

page 57

R. Grin

Clauses where et having


Exemple
select d.nom, avg(e.salaire) from Departement d join d.employes e group by d.nom having count(d.nom) > 3

Ces clauses peuvent comporter les mots-cls suivants : n [NOT] LIKE, [NOT] BETWEEN, [NOT] IN n AND, OR, NOT n [NOT] EXISTS n ALL, SOME/ANY n IS [NOT] NULL n IS [NOT] EMPTY, [NOT] MEMBER OF (pour les collections)
JPA page 59

R. Grin

R. Grin

JPA

page 60

10

having

order by
On peut choisir un ordre dans les valeurs ou objets renvoys Evidemment, il doit exister un ordre naturel dans les types utiliss pour le tri Il peut y avoir plusieurs critres de tri On peut choisir un ordre croissant (par dfaut) ou un ordre dcroissant (critre de tri suivi de DESC) Le critre de tri ne peut tre quune entit, un champ persistant ou un variable rsultat (voir gain dans lexemple du transparent suivant)
R. Grin JPA page 62

Restriction : la condition doit porter sur une proprit ou une association valeur unique de lexpression de regroupement (celle qui est dans le group by) ou sur une fonction de regroupement Par exemple

select e.nom, count(p) from Employe join e.projets p group by e having count(p) > 2
R. Grin JPA page 61

Exemple

Restrictions

select e from Employe e order by e.nom select e, d from Employe e join e.departement d order by d.nom, e.nom desc select e.nom, e.salaire + e.prime as gain from Employe order by gain

Si la clause select est une proprit, la clause order by ne peut utiliser que cette proprit ; la requte suivante est interdite :
select e.nom from Employe order by e.salaire

Un critre de tri ne peut comporter de fonction ; la requte suivante est interdite :


select d from Departement d join d.employes e order by avg(e.salaire)

R. Grin

JPA

page 63

R. Grin

JPA

page 64

Sous-requte (1)
Les clauses where et having peuvent contenir des sous-requtes Exemple :

Sous-requte (2)
{ALL | ANY | SOME} (sous-requte) fonctionne comme dans SQL Exemple :
select e from Employe e where e.salaire >= ALL ( select e2.salaire from Employe e2 where e2.departement = e.departement)

select e from Employe e where e.salaire >= ( select e2.salaire from Employe e2 where e2.departement = 10)

R. Grin

JPA

page 65

R. Grin

JPA

page 66

11

Sous-requte synchronise
Une sous-requte peut tre synchronise avec une requte englobante Exemple :

Sous-requte - exists
[not]exists fonctionne comme avec SQL Exemple :
select emp from Employe e where exists ( select ee from Employe ee where ee = e.epouse)

select e from Employe e where e.salaire >= ALL ( select e2.salaire from Employe e2 where e2.departement = e.departement)

R. Grin

JPA

page 67

R. Grin

JPA

page 68

Utilit de la jointure

Jointure
Une jointure permet de combiner plusieurs entits dans un select Rappel : il est aussi possible dutiliser plusieurs entits dans une requte grce la navigation Une jointure est le plus souvent utilise pour rsoudre les cas (interdit par JPA) o n lexpression du select serait une collection n la navigation partirait dune collection

page 69 R. Grin JPA page 70

d.employes.nom est interdit car d.employes est une collection Pour avoir les noms des employs dun dpartement, il faut utiliser une jointure

R. Grin

JPA

Types de jointures

Exemple

Il existe plusieurs types de jointures : n jointure interne (jointure standard join) n jointure externe (outer join)
n

Si on veut tous les employs dun dpartement, la requte suivante nest pas permise par la spcification JPA :
select d.employes from Departement d where d.nom = 'Direction'

jointure avec rcupration de donnes en mmoire (join fetch) jointure la SQL dans un where pour joindre suivant des champs qui ne correspondent pas une association (where e1.f1 = e2.f2)
JPA page 71

Une jointure est ncessaire :


select e from Departement d join d.employes e where d.nom = 'Direction'

R. Grin

R. Grin

JPA

page 72

12

Autres exemples

Jointure externe

select e.nom from Departement d join d.employes e where d.nom = 'Direction' select e.nom, parts.projet.nom from Employe e 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 73

select e, d from Employe e left join e.departement d

ramnera aussi les employs qui ne sont pas associs un dpartement

R. Grin

JPA

page 74

Jointure la SQL

Exemple
Soit une entit Candidature, sans association, qui contient des candidatures des formations Lentit contient les attributs suivants : id, nomP (identifie une personne), nomF (identifie une formation) Auto-jointure pour avoir la liste des personnes qui ont candidat plusieurs formations :
select c0.nomP, c1.nomF from Candidature c0, Candidature c1 where c0.nomP = c1.nomP and c0.nomF != c1.nomF order by c0.nomP
R. Grin JPA page 76

Les jointures que nous avons vues sappuient sur des associations entre entits Il est aussi possible deffectuer une jointure entre 2 entits sans sappuyer sur une association Il suffit dindiquer les valeurs qui devront tre gales dans la jointure

R. Grin

JPA

page 75

join fetch
Permet dviter le problme des N + 1 selects Les entits places droite de join fetch seront cres en mmoire en mme temps que lentit de la clause select (mais pas renvoyes par la requte) Le select SQL gnr sera une jointure externe qui rcuprera les donnes de toutes les entits associes en mme temps que les donnes des entits principales de la requte

R. Grin JPA page 77

Exemple

select e from Employe e join fetch e.departement

Cette requte rcuprera tous les employs mais, en plus, lappel de la mthode getDepartement() ne provoquera aucune interrogation de la base de donnes puisque le join fetch aura dj charg tous les dpartements des employs

R. Grin

JPA

page 78

13

Exemple
String texteQuery = "select e " + " from Employe as e " + " join fetch e.participations"; Query query = em.createQuery(texteQuery); listeEmployes = (List<Employe>)query.getResultList();

Doublons possibles avec join fetch


La requte SQL lance par un join fetch fait une jointure pour rcuprer les entits prcharges Ensuite, les entits prcharges sont enleves des lignes du rsultat pour quelles napparaissent pas dans le rsultat du query Ce traitement, impos par la spcification de JPA, peut occasionner des doublons dans le rsultat si le select renvoie des valeurs (pas des entits) Pour les viter, il faut ajouter loprateur DISTINCT dans le texte de la requte ou placer le rsultat dans une collection de type Set

R. Grin JPA page 80

Cet exemple prcharge les participations aux projets des employs


R. Grin JPA page 79

Produit cartsien (1)


Il existe aussi des variantes outer join de join fetch pour rcuprer dans le select des entits non jointes une autre entit

Le prchargement par join fetch de plusieurs collections dune mme entit peut occasionner un phnomne nuisible aux performances En effet, le select SQL gnr par le fournisseur de persistance peut rcuprer un produit cartsien des lments des collections Le fournisseur sarrange pour ne garder que les informations ncessaires mais le select peut renvoyer un trs grand nombre de lignes qui vont transiter par le rseau

R. Grin JPA page 82

R. Grin

JPA

page 81

Produit cartsien (2)


Dans le cas o les collections contiennent de nombreux lments il faut donc vrifier avec les logs du fournisseur si le select gnr renvoie effectivement un trop grand nombre de lignes et changer de stratgie de rcupration si cest le cas (rcuprer sparment les informations sur les collections) En effet, si 2 collections contiennent 20 lments, et si 1000 entits principales sont renvoyes le select renverra 400.000 lignes ! (au lieu de 40.000 si on ramne les informations avec 2 join fetch spars)

R. Grin JPA page 83

Exemple
Une entit principale ep avec 2 associations de lentit principale avec dautres entits e2 et e3 Pour rcuprer en mmoire les entits principales et associes, le select gnr risque dtre du type suivant (consulter les logs du fournisseur de persistance) :

select ep.*, e2.*, e3.* from EP ep left outer join E2 e2 on ep.id_e2 = e2.id left outer join E3 e3 on ep.id_e3 = e3.id
R. Grin JPA page 84

14

Fonctions
Pour les chanes de caractres : concat, substring, trim, lower, upper, length, locate (localiser une sous-chane dans une autre) Arithmtiques : abs, sqrt, mod, size (dune collection) Pour les date : current_date, current_time, current_timestamp De regroupement : count, max, min, avg Conditionnelles : case, coalesce, nullif qui sont les pendants des fonctions SQL

R. Grin JPA page 85

case
JPA 2.0 a introduit le case de SQL (peut tre utilis dans une clause where ou having ou mme dans un update (voir section suivante) Variante simple :

CASE valeur WHEN valeur1 THEN rsultat1 WHEN valeur2 THEN rsultat2 ELSE rsultatN END

valeur peut tre un attribut ou une expression de type


JPA page 86

R. Grin

case

Exemples de case

Variante gnrale
CASE WHEN condition1 THEN rsultat1 WHEN condition2 THEN rsultat2 ELSE rsultatN END

select a.description, case type(a) when Stylo then 'stylo' when Ramette then 'ramette' else 'autre type' end from Article a update Employe e set e.salaire = case e.indice when 1 then e.salaire * 1.1 else e.salaire * 1.2 end
page 87 R. Grin JPA page 88

R. Grin

JPA

coalesce

nullif

coalesce(expression1, expression2,...)

nullif(expression1, expression2) renvoie

renvoie la valeur de la 1re expression non gale null Exemple : coalesce(commission, salaire, 0) renvoie la valeur de la commission si elle nest pas null, sinon renvoie la valeur sil nest pas null, et renvoie 0 sinon

null si les 2 expressions sont gales, sinon renvoie la valeur de expression1 Peut servir pour une ancienne base de donnes dans laquelle les valeurs null sont en fait reprsentes par une certaine valeur Exemple : nullif(salaire, -1)

R. Grin

JPA

page 89

R. Grin

JPA

page 90

15

Fonction index
JPA 2.0 permet de conserver lordre dune liste grce une colonne de la BD La fonction index retourne la valeur de cette colonne (0 pour le 1er lment) Exemple :

Travail avec les collections


Une expression chemin dun select peut dsigner une collection Exemples : departement.employes facture.lignes La fonction size donne la taille de la collection La condition is [not] empty est vraie si la collection est [nest pas] vide La condition [not] member of indique si une entit appartient une collection
R. Grin JPA page 92

select e.nom, t.numero from Employe e join e.telephones t where index(t) = 0

affiche les noms des employs avec leur numro de tlphone class 1er dans la liste de leurs numro de tlphone
R. Grin JPA page 91

Exemples

Parcours dune collection


select d from Departement where e.employes is empty select e from Employe e where :projet member of e.participations.projet

La requte suivante ne donnera pas tous les produits lis une facture ; elle provoquera une exception lexcution
select distinct f.lignes.produit from Facture as f

En effet, il est interdit de composer une expression de chemin en partant dune expression qui dsigne une collection (f.lignes)

R. Grin

JPA

page 93

R. Grin

JPA

page 94

Parcours dune collection


Le plus simple est dutiliser un join dans le from avec un alias ( l dans lexemple cidessous) pour dsigner un lment qui parcourt la collection :
select distinct l.produit from Facture as f join f.lignes as l

API critres

Lautre solution, in , une ancienne syntaxe hrite dEJB 2, nest pas recommande

R. Grin

JPA

page 95

R. Grin

JPA

page 96

16

Introduction
API introduite par JPA 2.0 Tout ce qui peut tre fait avec JPQL peut ltre avec lAPI critres Les requtes JPQL sont des String qui peuvent contenir des erreurs (par exemple le nom dune classe qui nexiste pas) Lavantage de lAPI critres est que les requtes peuvent tre vrifies la compilation Linconvnient est que le code est un peu plus complexe crire, et sans doute moins lisible

R. Grin JPA page 97

Mtamodle
Le mtamodle un ensemble de classes qui reprsente les classes gres par le manager dentits ainsi que leur tat (leurs attributs) et les associations entre elles LAPI critre peut sutiliser de avec ou sans utilisation explicite du mtamodle Lutilisation explicite du mtamodle complique un peu lcriture des requtes mais permet de dtecter plus derreurs la compilation

R. Grin JPA page 98

Obtenir le mtamodle dune classe


Mtamodle canonique (1/2)


Les environnements de programmation pour JPA ou des fournisseurs de persistance offrent un programme qui permet de gnrer statiquement les classes du mtamodle (sinon le dveloppeur peut les crire lui-mme) Les classes gnres ont pour nom le nom des classes gres suffix par _ : Employe_ pour reprsenter lentit Employe

Dynamiquement en partant de Root :


Root<Dept> dept = cq.from(Dept.class); EntityType<Dept> Dept_ = dept.getModel();

Dynamiquement en rcuprant le mtamodle :


EntityMananger em = ; Metamodel m = em.getMetamodel(); EntityType<Dept> Dept_ = m.entity(Dept.class);

Statiquement (voir transparents suivants)


JPA page 99 R. Grin JPA page 100

R. Grin

Mtamodle canonique (2/2)


Ces classes ont des variables de classe pour chacune des proprits des classes gres qui servent dans les requtes : Employe_.nom, ce qui permettra de dtecter encore plus derreurs la compilation dans les requtes quavec le mtamodle obtenu dynamiquement Les exemples suivants comparent 4 faons dexcuter une requte : avec JPQL, sans mtamodle, avec un mtamodle dynamique et avec le mtamodle canonique statique

R. Grin JPA page 101

Exemple de classe du mta-modle canonique


@StaticModel(Employe.class) public class Employe_ { public static volatile SingularAttributes<Employe, Integer> id; public static volatile SingularAttributes<Employe, String> nom; public static volatile SingularAttributes<Employe, Departement> dept; public static volatile CollectionAttributes<Employe, Projet> projets; // Dautres public static volatile ... ... }
R. Grin JPA page 102

17

Avec JPQL
String s = "select e from Employe e where e.nom = Dupond"; Query query = em.createQuery(s); Employe emp = (Employe)query.getSingleResult();

API critre sans mtamodle


CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Employe> cq = cb.createQuery(Employe.class); Root<Employe> emp = cq.from(Employe.class); cq.select(emp). where(cb.equal(emp.get("nom"), "Bob")); TypedQuery<Employe> tq = em.createQuery(cq); Employe dupond = tq.getSingleResult();

R. Grin

JPA

page 103

R. Grin

JPA

page 104

Mtamodle dynamique
CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Employe> cq = cb.createQuery(Employe.class); Root<Employe> emp = cq.from(Employe.class); EntityType<Employe> employe_ = emp.getModel(); cq.select(emp).where(cb.equal( emp.get( employe_.getSingularAttribute("nom")), "Dupond")); TypedQuery<Employe> tq = em.createQuery(cq); Employe dupond = tq.getSingleResult();
R. Grin JPA page 105

Mtamodle canonique statique


CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Employe> cq = cb.createQuery(Employe.class); Root<Employe> emp = cq.from(Employe.class); cq.select(emp) .where(cb.equal(emp.get(Employe_.nom), "Dupond")); TypedQuery<Employe> tq = em.createQuery(cq); Employe dupond = tq.getSingleResult();

R. Grin

JPA

page 106

API complexe
LAPI contient de nombreuses interfaces et ne peut tre dtaille dans ce cours Nous nen donnerons quun aperu avec 2 exemples

Exemple (sans mtamodle)


CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Employe> cq = cb.createQuery(Employe.class); Root<Employe> emp = cq.from(Employe.class); cq.select(emp). where(cb.ge(emp.get("salaire").as(Double.class), 5000.0));

Cast obligatoire

R. Grin

JPA

page 107

R. Grin

JPA

page 108

18

Exemple plus complexe


CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<String> cq = cb.createQuery(String.class); Root<Client> client = cq.from(Client.class); Join<Facture,LigneFacture> ligne = client.join(Client_.factures) .join(Facture_.lignesFacture); cq.where(qb.equals( ligne.get(ligne_.produit) .get(Produit_.typeProduit), "imprimante")) .select(client.get(Client_.nom));

Oprations de modification en volume

En JPQL : select c.nom


from Client c join c.factures f join f.lignes l where l.produit.typeProduit = 'imprimante'
R. Grin JPA page 109 R. Grin JPA page 110

Utilit
Pour les performances il est parfois mauvais de charger toutes les donnes modifier dans des instances dentits En ce cas, JPQL permet de modifier les donnes de la base directement, sans crer les entits correspondantes

Cas dutilisation
Si on veut augmenter de 5% les 1000 employs de lentreprise il serait mauvais de rcuprer dans 1000 instances les donnes de chaque employs, de modifier le salaire de chacun, puis de sauvegarder les donnes Un simple ordre SQL
update employe set salaire = salaire * 1.05

sera normment plus performant JPQL permet de lancer cet ordre sans passer par JDBC
R. Grin JPA page 111 R. Grin JPA page 112

Exemple
em.getTransaction().begin(); String ordre = "update Employe e " + " set e.salaire = e.salaire * 1.05"; Query q = em.createQuery(ordre); int nbEntitesModif = q.executeUpdate(); em.getTransaction().commit();

Syntaxe
Les ordres de modification en volume rfrencent les classes et les proprits des classes mais ils ne crent aucune entit en mmoire et ils ne mettent pas jour les entits dj prsentes en mmoire update Entite as alias set alias.prop1 = val1, alias.prop2 = val2, where condition La condition peut tre aussi complexe que la condition dun select
R. Grin JPA page 114

R. Grin

JPA

page 113

19

Remarques
Les modifications doivent tre faites dans une transaction Le plus souvent il faut isoler le lancement de ces oprations dans une transaction part, ou au moins excuter ces oprations au dbut dune transaction avant la rcupration dans la base dentits touches par lopration En effet, les entits en mmoire ne sont pas modifies par lopration et elles ne correspondront alors donc plus aux nouvelles valeurs modifies dans la base de donnes

R. Grin JPA page 115

Version des entits


Les versions des entits modifies par les modifications en volume ne sont pas ncessairement mises jour (dpend des fournisseurs de persistance, donc pas portable) Il peut donc tre ncessaire dincrmenter explicitement le numro de version dans le update

R. Grin

JPA

page 116

Exceptions utilises par JPA


JPA nutilise que des exceptions non contrles (descendantes de RuntimeException) JPA utilise les 2 exceptions IllegalArgumentException et IllegalStateException du paquetage java.lang Sinon, toutes les autres exceptions sont dans le paquetage javax.persistence et hritent de PersistenceException
JPA page 118

Exceptions

R. Grin

JPA

page 117

R. Grin

Types dexception

PersistenceException et rollback

NonUniqueResultException NoResultException EntityNotFoundException EntityExistsException TransactionRequiredException RollbackException OptimisticLockException PessimisticLockException LockTimeoutException


R. Grin JPA page 119

Toute les exceptions de type PersistenceException marquent la transaction en cours pour un rollback (voir section suivante sur les transactions), sauf NoResultException, NonUniqueResultException (toutes les 2 lies getSingleResult) et LockTimeoutException

R. Grin

JPA

page 120

20

Exceptions dans les mthodes daccs aux proprits


Les RuntimeException marquent la transaction en cours pour un rollback Les exception contrles sont enveloppes dans une PersistenceException (non contrle) et la transaction en cours est marque pour un rollback

Transaction

R. Grin

JPA

page 121

R. Grin

JPA

page 122

2 types de transactions
Les transactions locales une ressource, fournies par JDBC sont attaches une seule base de donnes Les transactions JTA, ont plus de fonctionnalits que les transactions JDBC ; en particulier des oprations effectues dans plusieurs bases de donnes peuvent tre englobes dans une seule transaction

Transactions dans Java EE


Elles ne sont pas tudies dans ce cours

R. Grin

JPA

page 123

R. Grin

JPA

page 124

Transactions dans Java SE (sans serveur dapplications)


EntityTransaction
En dehors dun serveur dapplications, une application doit utiliser linterface javax.persistence.EntityTransaction pour travailler avec des transactions locales une ressource Une instance de EntityTransaction peut sobtenir par la mthode getTransaction() de EntityManager

Daprs la spcification JPA, dans Java SE, les fournisseurs de persistance doivent supporter les transactions locales une ressource, mais ne sont pas obligs de supporter les transactions JTA La dmarcation des transactions est choisie par le dveloppeur Les contextes de persistance peuvent couvrir plusieurs transactions

R. Grin JPA page 125

R. Grin

JPA

page 126

21

EntityTransaction
public interface EntityTransaction { public void begin(); public void commit(); public void rollback(); public void setRollbackOnly(); public boolean getRollbackOnly(); public boolean isActive(); }

Exemple
EntityManager em; ... try { em.getTransaction().begin() ... em.getTransaction().commit(); } finally { em.close(); }
page 127 R. Grin JPA page 128

R. Grin

JPA

Rollback (1)

Rollback (2)
Les instances dentits Java gardent les valeurs quelles avaient au moment du rollback Mais ces valeurs sont le plus souvent fausses Il est donc rare dutiliser ces entits en les rattachant par un merge un GE

En cas de rollback, n rollback dans la base de donnes n le contexte de persistance est vid ; toutes les entits deviennent dtaches

Le plus souvent il faut relancer des requtes pour rcuprer des entits avec des valeurs correctes

R. Grin

JPA

page 129

R. Grin

JPA

page 130

Transaction et contexte de persistance


Quand un GE nest pas gr par un container (cest le cas en dehors dun serveur dapplications) le contexte de persistance nest pas ferm la fin dune transaction Quand un GE est gr par un container (cest le cas avec un serveur dapplications) et que le contexte de persistance nest pas de type tendu (pas tudi dans ce cours), le contexte est ferm la fin dune transaction

R. Grin JPA page 131

Synchronisation dun GE avec une transaction


Synchronisation dun GE avec une transaction : le GE est enregistr auprs de la transaction ; un commit de la transaction provoquera alors automatiquement un flush du GE (le GE est averti lors du commit) En dehors dun serveur dapplications (avec Java SE), un GE est obligatoirement synchronis avec les transactions (quil a lances par la mthode begin() de EntityTransaction)

R. Grin JPA page 132

22

Modifications et commit
Les modifications effectues sur les entits gres sont enregistres dans la base de donnes au moment dun flush du contexte de persistance Si le GE est synchronis la transaction en cours, le commit de la transaction enregistre donc les modifications dans la base Les modifications sont enregistres dans la base, mme si elles ont t effectues avant le dbut de la transaction (avant tx.begin() dans Java SE)

R. Grin JPA page 133

Erreurs et problmes divers


Dmarrer une nouvelle transaction alors quil y en a dj une en cours lancera une IllegalStateException commit() et rollback() lancent la mme exception si aucune transaction nest active Si une erreur survient lors de rollback(), une PersistanceException sera lance Si une erreur survient lors de commit(), une RollbackException est lance

R. Grin JPA page 134

Marquage pour un rollback (1)


Dans les applications dentreprise, les transactions sont souvent gres par un serveur dapplications qui effectue lui-mme les commit et rollback Le code de lapplication ne peut lancer de commit ou de rollback ; elle peut cependant marquer la transaction pour un rollback par la mthode setRollbackOnly()

Marquage pour un rollback (2)


Le plus souvent la mthode setRollbackOnly est appele dans un bloc catch lorsquune exception sest produite Plus gnralement elle peut tre appele lorsquune condition quelconque ne permet pas que la transaction soit valide Il est impossible denlever une marque pour un rollback

Le serveur dapplications sera alors oblig de terminer la transaction par un rollback


JPA page 135 R. Grin JPA page 136

R. Grin

Marquage pour un rollback (3)


Cette mthode (ainsi que la mthode getRollbackOnly) ne peut tre appele dans le cas o lapplication gre elle-mme les transactions Cest le cas en particulier des applications qui ne sont pas gres par un serveur dapplications ; ces 2 mthodes sortent donc du cadre fix pour ce cours

Exceptions et transactions
Il faut prendre garde de ne pas laisser des transactions ouvertes dans le cas o des flushs ont transfr des commandes vers la base de donnes En effet, les blocages effectues dans la base de donnes ne seront alors pas librs Une cause derreur peut tre la leve dune exception qui fait sortir dune mthode, et dont le traitement ne ferme pas la transaction en cours (par commit ou rollback)
R. Grin JPA page 138

R. Grin

JPA

page 137

23

GE et threads
Une fabrique de GE peut tre utilise sans problme par plusieurs threads Mais un GE ne doit tre utilis concurremment que par un seul thread

Concurrence

R. Grin

JPA

page 139

R. Grin

JPA

page 140

Entits et threads
Les entits ne sont pas prvues pour tre utilises par plusieurs threads en mme temps Si a doit tre le cas, lapplication doit prendre toutes ses prcautions pour viter les problmes Cest aussi le rle de lapplication dempcher quune entit ne soit gre par plusieurs GE en mme temps Le rle du fournisseur de persistance nintervient pas pour ces cas

R. Grin JPA page 141

Concurrence BD

Le fournisseur de persistance peut apporter automatiquement une aide pour viter les problmes daccs concurrents aux donnes de la BD, pour les entits gres par un GE

R. Grin

JPA

page 142

Exemple de problme de concurrence BD


Gestion de la concurrence
JPA suppose aussi que la BD a le mode disolation READ COMMITED (voir cours sur les BD) et que les critures dans la base nont lieu quau moment dun flush Par dfaut (sans aucun blocage explicite par lock), le fournisseur de persistance gre les problmes daccs concurrents aux entits gres par un GE, qui ont un attribut version , avec une stratgie optimiste

R. Grin JPA page 144

Une entit est rcupre depuis la BD (par un find par exemple)

Lentit est ensuite modifie par lapplication puis la transaction souhaite valider cette modification Si une autre transaction a modifi entretemps les donnes de la BD correspondant lentit, la transaction ne doit pas tre valide pour viter les problmes de mises jour perdues
R. Grin JPA page 143

24

@Version (1/2)
Annote un attribut dont la valeur reprsente un numro de version (incrment chaque modification), utilis pour savoir si ltat dune entit a t modifi entre 2 moments diffrents Correspond une colonne de la base de donnes La valeur de lattribut et de la colonne de la base de donnes sont mises jour automatiquement par JPA

@Version (2/2)
Lattribut doit tre de type int, Integer, short, Short, long, Long ou java.sql.TimeStamp (si possible, viter ce dernier type) et ne doit pas tre null dans la base de donnes Entit versionne : possde un attribut annot @Version (ou le tag correspondant dans les fichiers XML)

R. Grin

JPA

page 145

R. Grin

JPA

page 146

Exemple
@Version private int version;

Modification automatique de la version


La version est mise jour automatiquement n si le champ modifi est un champ ordinaire n ou un champ li une association dont lentit possde la cl trangre (elle en est donc propritaire) JPA nimpose pas que la version soit mise jour lors dune opration de modifications en volume

R. Grin

JPA

page 147

R. Grin

JPA

page 148

Modification de la version
Lapplication ne doit jamais modifier un tel attribut (seul JPA le modifie), sauf, ventuellement lors des oprations de modifications en volume Si on veut mettre jour la version dans le cas dune association dont lentit ne possde pas la cl trangre, il faut utiliser lock avec loption dincrment de la version (tudi ci-aprs)

Protection par dfaut des entits versionnes


Mme sans aucun blocage explicite, JPA protge les donnes contre les accs concurrent Cette protection minimale empche la situation suivante : une transaction t1 ne pourra valider des modifications sur des donnes lues dans la base que si ces donnes nont pas t modifies par une autre transaction entre le moment o t1 les a lues et le moment o elle lance un commit
R. Grin JPA page 150

R. Grin

JPA

page 149

25

Protection des entits non versionnes


Le fournisseur de persistance peut aussi effectuer automatiquement ce contrle sur une entit non versionne (par exemple en comparant les donnes lues avec les donnes de la base au moment du commit), mais JPA ne limpose pas Pour la portabilit il faut donc versionner les entits sujettes des accs concurrents (ou utiliser les blocages pessimistes)

R. Grin JPA page 151

Exception

Si la transaction est invalide en liaison dun blocage optimiste, une exception OptimisticLockException est lance

R. Grin

JPA

page 152

lock(entite, mode)
Sert protger une entit contre les accs concurrents pour les cas o la protection offerte par dfaut ne suffit pas (on a vu que, mme sans aucun blocage explicite avec lock, JPA protge dj des accs concurrents avec une stratgie optimiste) Cette entit doit tre versionne (sinon, le traitement nest pas portable) et dj gre par le gestionnaire dentits

R. Grin JPA page 153

Autres mthodes pour le blocage


Il est possible dindiquer un mode de blocage pour les entits ramenes par un find (en 3me paramtre de la mthode) ou un query (mthode setLockMode de linterface Query) refresh permet aussi dindiquer un blocage pour lentit dont on rafrachit ltat (en 2me paramtre) Ces mthodes doivent tre lances dans une transaction ( part setLockMode, mais le query doit tre lanc dans une transaction)

R. Grin JPA page 154

Modes de blocage

Modes de blocage optimistes


OPTIMISTIC : si une autre transaction modifie lentit bloque, la transaction t1 qui a bloqu lentit sapercevra que le numro de version a chang et sera invalide, mme t1 na pas modifi la donne OPTIMISTIC_FORCE_INCREMENT : comme OPTIMISTIC, mais en plus lattribut de version de lentit bloque est incrment, mme si lentit na pas t modifie par la transaction t1 (utilit explique dans les transparents suivants

R. Grin JPA page 156

Lnumration LockModeType (paquetage javax.persistence) dfinit 5 modes n OPTIMISTIC (READ en JPA 1) n OPTIMISTIC_FORCE_INCREMENT (WRITE en JPA 1) n PESSIMISTIC_READ n PESSIMISTIC_WRITE n PESSIMISTIC_FORCE_INCREMENT

R. Grin

JPA

page 155

26

Diffrence avec le traitement par dfaut


Utilit du blocage OPTIMISTIC


Ce blocage est utile pour faire des bilans pour lesquels les donnes ne doivent pas tre modifies du dbut la fin du traitement Il peut aussi tre utile si 2 valeurs sont troitement lies de telle sorte que la modification dune des valeurs par une transaction T empche la modification de lautre par une autre transaction ; pour modifier une des 2 valeurs, T doit alors bloquer aussi lautre valeur, mme si celle-ci nest pas modifie par la transaction T

R. Grin JPA page 158

Linvalidation de la transaction arrivera mme si lentit bloqu par un lock OPTIMISTIC na pas t modifie par la transaction

R. Grin

JPA

page 157

Un exemple (1)
Un bilan qui calcule le total des salaires des employs pour chaque dpartement doit interdire quun employ ne change de dpartement pendant le traitement, en passant du dpartement 10 au dpartement 20 Sinon, cet employ sera compt 2 fois : aprs avoir fait le calcul du total du dpartement 10, on va faire une requte pour rcuprer les employs du dpartement 20 et retrouver lemploy dj dcompt dans le dpartement 10

R. Grin JPA page 159

Un exemple (2)

Pour viter ce problme, les employs peuvent tre bloqus en mode OPTIMISTIC, au fur et mesure de leur prise en compte pour le calcul du total des salaires de leur dpartement

R. Grin

JPA

page 160

OPTIMISTIC_FORCE_INCREMENT
Force une incrmentation du numro de version Pour certains traitements il est intressant de considrer que lentit a t modifie mme si aucun de ses attributs na t modifi, par exemple lorsquune association avec une autre entit a t modifie Dans lexemple qui suit, le blocage OPTIMISTIC_FORCE_INCREMENT vite en quelque sorte les problmes de lignes fantmes avec les associations qui concernent une entit

R. Grin JPA page 161

OPTIMISTIC_FORCE_INCREMENT

En effet, sans le blocage OPTIMISTIC_FORCE_INCREMENT ( OFI pour la suite), le fournisseur de persistance incrmente automatiquement le numro de version si une entit est modifie mais pas si les liens des associations qui partent de lentit sont modifies lorsque lentit nest pas propritaire de lassociation (voir cependant la remarque qui suit lexemple donn dans les transparents suivants)
JPA page 162

R. Grin

27

Utilit des blocages OFI (1)


Une en-tte de facture contient un champ dans lequel est stock le total de la facture Supposons que le calcul de ce total est effectu par un processus part du processus de lajout des lignes de la facture Lorsquune ligne de facture est ajoute une facture, len-tte de la facture nest pas modifie donc le fournisseur de persistance nincrmente pas le numro de version de len-tte

R. Grin JPA page 163

Utilit des blocages OFI (2)


Une ligne peut tre ajoute une facture sans que le traitement qui calcule le total ne sen rende compte ; il y aura inconsistance entre ce total et les lignes de la facture Si len-tte est bloque en criture pendant lajout dune ligne de facture, le traitement qui effectue le calcul du total sapercevra que la facture a chang pendant le calcul puisque le numro de version aura t incrment et il ny aura pas inconsistance

R. Grin JPA page 164

Remarque
Certains fournisseurs de persistance comme Hibernate incrmentent le numro de version quand les collections dune entit sont modifies Dans ce cas le blocage OFI sera tout de mme utile si, par exemple, un des lments de la collection est modifi, par exemple le prix dun produit compris dans la facture

Blocages pessimistes (1/3)


Lorsque la probabilit de conflits est trop importante, la stratgie optimiste conduit de trop nombreux rollback En ce cas il vaut mieux bloquer ds le dbut laccs des autres transactions aux donnes que lon manipule JPA 2.0 a ajout des blocages pessimistes Comme les blocages optimistes, ils permettent dviter les lectures non rptables
R. Grin JPA page 166

R. Grin

JPA

page 165

Blocages pessimistes (2/3)


Le blocage dure jusqu la fin de la transaction Aucune autre transaction du SGBD sous-jacent ne pourra modifier ou supprimer les donnes bloques Si le blocage est FORCE_INCREMENT ou WRITE, la transaction qui a bloqu pourra modifier ou supprimer les donnes bloques (un blocage READ peut tre partag avec une autre transaction et donc empcher la transaction de modifier les donnes)

R. Grin JPA page 167

Blocages pessimistes (3/3)


Les versions des entits bloques en mode pessimiste et modifies sont incrmentes

R. Grin

JPA

page 168

28

Porte du blocage
Lnumration PessimisticLockScope contient les 2 valeurs NORMAL et EXTENDED En mode EXTENDED, les donnes correspondant une association ou une collection dlments, qui sont dans une table jointe, sont aussi bloques La porte peut tre indique avec la proprit javax.persistence.lock.scope dans diffrentes mthodes des classes EntityManager et Query comme la mthode lock(entit, mode, proprits)

R. Grin JPA page 169

Modes de blocage pessimistes


PESSIMISTIC_WRITE : le mode le plus courant ; les donnes de la base correspondant aux entits bloques ne pourront tre modifies par dautres transactions ; blocage exclusif PESSIMISTIC_READ : assure des lectures rptables ; blocage partageable PESSIMISTIC_FORCE_INCREMENT : comme WRITE avec, en plus, la mise jour de la version, mme si lentit na pas t modifie

R. Grin JPA page 170

PESSIMISTIC_WRITE
Lentit est bloque (pour les autres transaction) ds sa modification par la transaction qui a lanc le lock ; correspond un select for update dans la base de donnes Empche les autres transactions de bloquer en mode PESSIMISTIC_READ ou _WRITE (jusqu la fin de la transaction) Les autres transactions devront attendre la fin de la transaction pour pouvoir leur tour modifier lentit

R. Grin JPA page 171

PESSIMISTIC_READ
Mode utilis par certaines bases de donnes pour empcher les lectures non rptables, sans bloquer par un select for update Les autres transactions ne peuvent modifier les donnes qui correspondent lentit mais peuvent les lire Empche les autres transactions de bloquer en mode PESSIMISTIC_WRITE mais pas de bloquer en mode PESSIMISTIC_READ

R. Grin JPA page 172

Changement automatique de mode


Exception
Lorsque le fournisseur de persistance ne peut obtenir un blocage pessimiste et que le SGBD sous-jacent ne fait quun rollback de la requte (et pas de la transaction toute entire), une LockTimeoutException doit tre lance et la transaction ne doit pas tre marque pour un rollback Si le problme est plus grave, une PessimisticLockException est lance et la transaction est marque pour un rollback

R. Grin JPA page 174

Lorsquune transaction a bloqu une entit en mode PESSIMISTIC_READ et quelle modifie ensuite lentit, le mode passe automatiquement en PESSIMISTIC_WRITE

R. Grin

JPA

page 173

29

Entit dtache

Les entits dtaches sont surtout utiles dans les applications multi-tiers (avec Java EE et un serveur dapplications) Cette section survole les possibilits offertes par les entits dtaches

R. Grin

JPA

page 175

R. Grin

JPA

page 176

Cas dutilisation des entits dtaches


Une application multi-tiers Le serveur dapplication rcupre des donnes dans la BD Ces donnes sont passes la couche client, montres lutilisateur qui peut les modifier Les modifications sont repasses au serveur et enregistres dans la BD Les entits dtaches facilitent limplmentation dun tel cas dutilisation

R. Grin JPA page 177

Utilisation des entits dtaches


Une fois dtaches les entits peuvent tre passes la couche cliente La couche cliente peut modifier les entits dtaches Ces entits peuvent ensuite tre rattaches un GE et les modifications effectues dans la couche cliente peuvent tre alors enregistres dans la base de donnes lors d'un flush

R. Grin JPA page 178

Rattachement
La mthode merge de EntityManager permet dobtenir une entit gre partir dune entit dtache Sa signature : <T> T merge(T entit)

Attention, lentit passe en paramtre nest pas rattache ; cest lentit renvoye par la mthode merge qui est rattache ; cette entit a le mme tat et la mme cl primaire que lentit passe en paramtre
JPA page 179

Si lentit passe en paramtre de merge est dj gre par le GE (cest lidentificateur de lentit qui permet de savoir si lentit est dj gre), ses valeurs sont crases par les valeurs de lobjet pass en paramtre et elle est renvoye par la mthode merge

R. Grin

R. Grin

JPA

page 180

30

tat dune entit dtache


tat dune entit


Pour des raisons de performances, l'tat dune entit gre par un GE peut ne avoir t compltement rcupr dans la BD (rcupration retarde ; lazy) Le reste de ltat ne sera rcupr, avec laide du GE, que lorsque lentit en aura vraiment besoin Si lentit est dtache alors quune partie de son tat na pas encore t rcupre, la partie manquante de lentit dtache ne sera pas disponible

R. Grin JPA page 182

Ltat dune entit dtache peut ne pas tre entirement disponible

R. Grin

JPA

page 181

Attribut disponible

Association dune entit dtache


Un attribut persistant dune entit est immdiatement disponible dans les 2 cas suivants : n lattribut a dj t utilis n lattribut na pas t marqu par fetch=LAZY (par dfaut, les valeurs des attributs sont charges en mmoire)

Si une association dun objet dtach a le mode de rcupration LAZY, il est possible que lassociation ne puisse tre rcupre (dpend des circonstances et des fournisseurs de JPA)

R. Grin

JPA

page 183

R. Grin

JPA

page 184

Association lazy disponible


Rendre accessible ltat dune entit dtache


2 solutions pour accder tout ltat (valeurs dans la base de donnes) dune entit dtache Lapplication rcupre tout ltat de lentit gre avant le dtachement Lapplication rattache lentit par la mthode merge le temps de rcuprer ltat manquant

Si une association dun objet dtach a le mode de rcupration LAZY, il est possible de naviguer travers cette association si n lapplication a dj effectu cette navigation n ou si lassociation a t charge par un join fetch lors dune requte

R. Grin

JPA

page 185

R. Grin

JPA

page 186

31

Rcuprer une association avant le dtachement


Entit dtache et concurrence


Avant que les modifications sur lentit dtache ne soient enregistres dans la BD, lentit doit tre rattache un contexte de persistance (celui dorigine ou un autre) A ce moment, ou au moment du commit qui enregistre vraiment les modifications, le contexte de persistance vrifie quil ny a pas de conflit de concurrence

Si le but est une entit (OneToOne ou ManyToOne), il suffit de lire une des proprits de lentit Si le but est une collection (OneToMany ou ManyToMany), lappel de la mthode size() de la collection suffit le plus souvent

R. Grin

JPA

page 187

R. Grin

JPA

page 188

Conflit de concurrence
Si les donnes de la BD associe un objet dtach ont t modifies depuis le dtachement de lobjet, merge lance une exception Tout se passe donc comme si un conflit de concurrence avait t dtect (avec une stratgie optimiste)

Dtachement automatique
Dans Java SE, quelques situations provoquent un dtachement automatique des entits gres : n Aprs un rollback n Aprs un clear du GE n Aprs la fermeture du GE n Un nouvel objet cr partir partir dune entit srialise est dtach (situation frquente pour les applications distribues)
JPA page 190

R. Grin

JPA

page 189

R. Grin

Fichiers de configuration

Pour fonctionner JPA a besoin de


n n

Configuration dune unit de persistance

savoir comment se connecter la base de donnes avoir les informations pour faire le mapping entre les classes entits et les tables de la base

Les informations sur la base de donnes sont donnes le plus souvent par le fichier META-INF/persistence.xml Les informations sur le mapping sont donnes le plus souvent par des annotations mais elles peuvent aussi tre donnes par le fichier META-INF/orm.xml

page 191 R. Grin JPA page 192

R. Grin

JPA

32

Fichier persistence.xml

Ces informations sont lues au moment o une fabrique de gestionnaire dentits est cre

Les informations hors mapping sont donnes le plus souvent dans un fichier persistence.xml Dans un environnement non gr, ce fichier doit se situer dans le rpertoire META-INF dun des rpertoires du classpath Dans un serveur dapplications, le rpertoire META-INF peut se trouver divers endroits : dans WEB-INF/classes, un fichier jar de WEBINF/lib, un fichier jar de la racine dun fichier EAR, (voir spcification pour la liste complte)

page 193 R. Grin JPA page 194

R. Grin

JPA

Configuration dune unit de persistance


Dans un environnent non gr par un serveur dapplications, il est ncessaire de donner les informations pour la connexion la base de donnes Souvent une application nutilise quun seul compte utilisateur dans la base de donnes ; en ce cas, le nom et le mot de passe de ce compte sont donns dans le fichier persistence.xml

R. Grin JPA page 195

Configuration dune unit de persistance


Dans un environnent gr la source de donnes est le plus souvent dj dfinie dans le serveur dapplications et il suffit alors de donner le nom (JNDI) de la source de donnes dans le fichier persistence.xml Il est cependant possible aussi de dfinir la source de donnes dans lapplication avec lannotation @DataSourceDefinition, au lieu de la dfinir dabord dans le serveur dapplication

R. Grin JPA page 196

Fichier persistence.xml

persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version= "1.0" > <persistence-unit name="Employes" transaction-type="RESOURCE_LOCAL"> <class>p1.Employe</class> noms des classes gres <class>p1.Dept</class> <properties> . . . <! Voir transparent suivant--> </properties> </persistence-unit> </persistence>
R. Grin JPA page 198

Le fichier persistence.xml peut aussi donner dautres informations, comme


n

les noms des classes gres dont les attributs seront enregistrs dans la base (entits, classes Embeddable, classes mapped superclasses ) ; cest obligatoire dans un environnement non gr par un serveur dapplication la configuration de lenvironnement de mis au point (enregistrement dans les journaux/logging, affichage des ordres SQL lancs dans le SGBD,) des proprits particulires au driver du fournisseur de persistance
JPA page 197

R. Grin

33

Section properties
La section properties dpend du fournisseur de persistance Elle contient les informations pour la connexion mais aussi dautres informations pour le logging ou la cration automatique des tables si elle nexistent pas dj ; il faut consulter la documentation du fournisseur

Exemple de section properties


<properties> <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/> <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@...:INFO "/> <property name="javax.persistence.jdbc.user" value="toto"/> <property name="javax.persistence.jdbc.password" value="mdp"/> </properties>
R. Grin JPA page 200

R. Grin

JPA

page 199

Source de donnes

Configuration dynamique (1)


Les informations pour la connexion la base, en particulier le nom et le mot de passe de connexion la base, peuvent ntre connues qu lexcution et pas au moment de lcriture du code En ce cas, il est possible de ne donner les informations que lors de la cration de la fabrique par la classe Persistence

Lorsque JPA est utilis avec un serveur dapplications, une source de donnes fournie par le serveur dapplications est le plus souvent utilise pour obtenir les connexions (voir DataSource dans le cours sur JDBC) On pourra alors trouver :
<persistence-unit name="Employe"> <jta-data-source>jdbc/EmployeDS</jtadata-source> </persistence-unit name=Employe>

R. Grin

JPA

page 201

R. Grin

JPA

page 202

Configuration dynamique (2)


Exemple de configuration dynamique


// Saisie du nom et du mot de passe . . . // Configuration de la connexion Map props = new HashMap(); props.put("eclipselink.jdbc.user", nom); props.put("eclipselink.jdbc.password", mdp); EntityManagerFactory emf = Persistence.createEntityManagerFactory( "employes", props);

Il suffit de passer la mthode createEntityManagerFactory une map qui contient les proprits qui crasent les valeurs contenues dans persistence.xml

R. Grin

JPA

page 203

R. Grin

JPA

page 204

34

Les ajouts de EclipseLink


EclipseLink a des extensions par rapport la norme JPA Par exemple, n logging n gnration automatique de tables n

Gnration automatique des tables


La proprit eclipselink.ddl-generation permet de crer automatiquement les tables au moment de la cration de la fabrique de gestionnaires dentits Cette proprit peut avoir 3 valeurs : n none : aucune cration automatique n create-tables : les tables sont cres si elles nexistent pas dj n drop-and-create-tables : si une table existe dj, elle est dabord supprime avant dtre recre (utile pour les tests)

R. Grin JPA page 206

R. Grin

JPA

page 205

Exemple
<properties> . . . <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> </properties>

eclipselink.ddl-generation.output-mode

indique ce qui sera fait avec les fichiers DDL Valeurs possibles : n sql-script gnre les fichiers mais ne les excute pas n database excute les ordres DDL mais ne gnre pas les fichiers n both gnre les fichiers et les excute (valeur par dfaut)
JPA page 208

R. Grin

JPA

page 207

R. Grin

eclipselink.application-location indique le nom du rpertoire qui contiendra les fichiers contenant les ordres DDL de cration et de suppression des tables (le rpertoire courant par dfaut)

eclipselink.create-ddl-jdbc-file-name

indique le nom du fichier qui contiendra les ordres de cration des tables ; par dfaut, createDDL.jdbc

eclipselink.drop-ddl-jdbc-file-name

idem pour la suppression des tables ; par dfaut, dropDDL.jdbc

R. Grin

JPA

page 209

R. Grin

JPA

page 210

35

logging (1)

logging (2)
n

La proprit eclipselink.logging.level peut avoir les valeurs n OFF : aucune information n SEVERE : uniquement les erreurs n WARNING : les avertissements (et les erreurs) n INFO (valeur par dfaut) : assez peu
dinformation en plus
n

FINE : donne des informations sur les ordres


SQL utile pendant les tests et la mise au point

FINER : encore plus dinformations, par exemple


sur les transactions

FINEST : encore plus dinformations, par


exemple sur lutilisation des squences

CONFIG : donne des informations au moment du


dploiement sur la configuration

R. Grin

JPA

page 211

R. Grin

JPA

page 212

Placement des fichiers XML


Par dfaut les fichiers XML contenant les mta donnes sont places dans le fichier META-INF/orm.xml, sous un rpertoire du classpath Il est possible dindiquer dautres emplacements avec le tag <mapping-file> dans le fichier persistence.xml qui dfinit lunit de persistance

Fichiers XML

R. Grin

JPA

page 213

R. Grin

JPA

page 214

Exemple
<persistence-unit name="xxxx"> ... <mapping-file>META-INF/queries.xml </mapping-file> <mapping-file>META-INF/entities.xml </mapping-file> </persistence-unit>

Mta-donnes par dfaut


Llment <persistence-unit-defaults> contient des valeurs par dfaut qui sappliquent toutes les entits de lunit de persistance Les sous-lments peuvent tre : <schema> (donner le nom du schma relationnel), <catalog> (idem <schema> pour les SGBD qui supportent les catalogues), <access> (accs pour toutes les classes non annotes), <cascade-persist> (pour imposer la persistance par transitivit) et <entitylisteners> (couteurs par dfaut)
page 215 R. Grin JPA page 216

R. Grin

JPA

36

Fichiers XML annotations


Avantages des annotations : n mta donnes proches du code n pas besoin de donner le contexte comme dans les fichiers XML n plus simple Inconvnients : n changement des mta donnes ncessite une recompilation Les informations donnes dans les fichiers XML lemportent sur les annotations

R. Grin JPA page 217

Fichiers XML annotations


Les annotations sont le plus souvent utilises Les fichiers de configuration XML peuvent tre prfrs lorsque linformation n est dpendante de lenvironnement dexcution ; par exemple pour les noms de tables ou de colonnes n concerne plusieurs classes ; par exemple @TableGenerator qui donne le nom de la table qui gnre automatiquement les cls didentification des entits
JPA page 218

R. Grin

Exemple de fichier orm.xml (en-tte)


<?xml version="1.0" encoding="UTF-8" ?> <entity-mappings xmlns="http://java.sun.com/xml/ns/persisten ce.orm" xmlns:xsi:"http://www.w3.org/2001/XMLSchema -instance" xsi-schemaLocation = "http://java.sun.com/xml/ns/persistence.xml http://java.sun.com/xml/ns/persistence/orm_ 1_0.xsd" version="1.0">

Exemple de fichier orm.xml (fin)


<entity class="jpa.Employe"> <table name="EMP" /> <named-query name="findEmpByName" <query>select e from Employe e where e.nom like :nomEmploye</query> </named-query> </entity> </entity-mappings>

R. Grin

JPA

page 219

R. Grin

JPA

page 220

Utilit des DAO ?


La possibilit de dtacher et rattacher une entit rend souvent les DTO inutiles (voir cours sur DAO et modles de conception associs) Puisque JPA augmente fortement la portabilit du code charg de la persistance, est-ce que les DAOs sont encore ncessaires ?

JPA et DAO

R. Grin

JPA

page 221

R. Grin

JPA

page 222

37

Les DAOs ne sont pas toujours utiles


Pour les petites applications existence courte, avec peu de fonctionnalits mtier , lutilisation directe de JPA depuis le code mtier (sans utilisation de DAOs) simplifie le code li la persistance Les DAO ne sont alors pas vraiment utiles car JPA offre malgr tout une meilleure portabilit que JDBC et lutilisation des DAOs rend le code un peu plus complexe

Les DAOs ne sont pas toujours utiles


Dautant plus que code gnr automatiquement partir de la structure dune base de donnes par les IDE tels NetBeans pour les applications Web de type CRUD utilisent directement JPA et ne comportent pas de DAOs La tentation est donc grande de ne pas utiliser de DAOs

R. Grin

JPA

page 223

R. Grin

JPA

page 224

Les DAOs sont encore utiles


Cependant, pour les applications plus complexes, les DAOs peuvent apporter une meilleure abstraction et une meilleure factorisation du code li la persistance Les dtails techniques lis JPA (ou une version de JPA) peuvent tre cachs dans la couche DAO Les DAOs pourront aussi faciliter le passage ventuel un autre type de persistance, par exemple un SGBD objet

R. Grin JPA page 225

Les DAOs sont encore utiles


Evidemment les DAOs sont presque indispensables pour les applications qui utilisent plusieurs types de persistance pour les mmes donnes (voir cas dutilisation donn au dbut du cours sur les DAOs) Utiliser ou non des DAOs est donc une des premires questions se poser lorsque lon dveloppe une application qui accde une base de donnes

R. Grin

JPA

page 226

Exemple de factorisation du code


Un DAO peut contenir des mthodes spcialement adaptes au mtier Par exemple, une mthode qui renvoie la liste des candidats qui ont obtenu leur examen avec une certaine mention, passe en paramtre Cette mthode peut tre appele de plusieurs endroits du code mtier Le code qui lutilisera sera plus simple crire que sil utilisait directement JPA

R. Grin JPA page 227

Variantes des DAOs


Parmi toutes les variantes des mthodes des DAOs (voir cours sur les DAOs), celles qui prennent en paramtre ou qui renvoient des objets (des entits JPA dans ce cas) sont le plus souvent choisies En effet, les entits dtaches peuvent jouer le rle des DTOs qui sont donc inutiles, et les variantes qui utilisent plusieurs paramtres dont les valeurs correspondent aux proprits des objets compliquent inutilement le code

R. Grin JPA page 228

38

DAOs gnriques
La gnricit permet dcrire une classe mre gnrique de tous les DAOs, ce qui allge dautant les classes filles reprsentant chacune des classes DAOs Le type des entits gres et le type de lidentificateur sont les paramtres de type de ce DAO gnrique Les transparents suivants sont un exemple dimplmentation que vous pouvez modifier votre convenance

R. Grin JPA page 229

Interface DAO gnrique


public interface DaoGenerique<T,ID extends Serializable> { T findById(ID id); List<T> findAll(); void create(T objet); void delete(T entite); T update(T entite); } T est le type de lentit ID est le type de lidentificateur de lentit
R. Grin JPA page 230

Interface DAO pour une entit


Classe DAO gnrique (1)


public abstract class DaoGeneriqueJpa<T, ID extends Serializable> implements DaoGenerique<T, ID> { private Class<T> classeEntite; private EntityManager em; public DaoGeneriqueJpa() { // classe concrte de T passe find this.classeEntite = (Class<T>) ((ParameterizedType)getClass(). .getGenericSuperclass()) .getActualTypeArguments()[0]; }
R. Grin JPA page 232

public interface StyloDao extends DaoGenerique<Stylo, Long> { }

On peut ajouter des mthodes adapte au mtier , comme cette mthode qui renvoie toutes les marques de stylos en vente :
public interface StyloDao extends DaoGenerique<Stylo, Long> { List<String> findMarques(); }

R. Grin

JPA

page 231

Classe DAO gnrique (2)


public void insert(T objet) { em.persist(objet); } public void delete(T objet) { em.remove(objet); } public T findById(ID id) { return em.find(classeEntite, id); } public T update(T entite) { return em.merge(entite); }
R. Grin JPA page 233

Classe DAO gnrique (3)


public void setEntityManager(EntityManager em) { this.em = em; } protected EntityManager getEntityManager() { return this.em; } }

R. Grin

JPA

page 234

39

DAO pour une entit


public class StyloDaoJpa extends DaoGeneriqueJpa<Stylo, Long> implements StyloDao { public List<Stylo> findAll() { Query query = getEntityManager() .createNamedQuery("Stylo.findAll"); return (List<Stylo>)query.getResultList(); } }
R. Grin JPA page 235 R. Grin

DAO et multitche

Un DAO qui utilise JPA contient une instance de EntityManager qui nest pas threadsafe ; il ne faut donc pas le partager entre plusieurs threads

JPA

page 236

Utilit
Tous les fournisseurs de persistance utilisent un cache de second niveau (en plus du contexte de persistance) pour viter des accs aux bases de donnes, et donc amliorer les performances Tous les gestionnaires dentits dune mme unit de persistance utilisent le mme cache de second niveau Si une donne est lue par un gestionnaire et garde dans le cache, elle pourra tre lue par les autres gestionnaires sans accs la BD

page 237 R. Grin JPA page 238

Cache des donnes

R. Grin

JPA

Utilit

Utilisation des caches


Il nest pas toujours facile dutiliser correctement le cache de 2me niveau Le plus souvent on peut se contenter dindiquer quelles classes utiliseront ce cache Par exemple, il peut tre trs intressant dutiliser un cache pour des classes dont les donnes ne changent que trs rarement comme les noms des pays

La spcification JPA 2 standardise en partie lutilisation du cache de 2me niveau ; il faut consulter la documentation du fournisseur de persistance pour connatre les autres possibilits ventuelles

R. Grin

JPA

page 239

R. Grin

JPA

page 240

40

Problmes ventuels
Parfois ce cache pose des problmes si la base de donnes est utilise en parallle par dautres applications Par exemple, si des entits lies une entit sont supprimes de la base en dehors de lapplication, le cache peut penser modifier une ligne avec un UPDATE au lieu den insrer une nouvelle avec un INSERT, ce qui provoque une erreur

R. Grin JPA page 241

Solutions (1)
Lutilisation de la mthode refresh de EntityManager permet de rcuprer dans la base de donnes des donnes fraiches , sans jamais passer par le cache Un blocage pessimiste peut parfois tre la solution si on souhaite interdire la modification de lignes par une autre application (implmentation dpendante du fournisseur de persistance)

R. Grin JPA page 242

Solutions (2)
Parfois la seule solution est de vider le cache ou dindiquer au fournisseur de ne pas utiliser le cache pour effectuer certaines oprations (la faon de faire dpend en partie du fournisseur de persistance) JPA 2 permet deffectuer certains rglages pour optimiser lutilisation du cache, et viter les problmes lis aux donnes qui ne sont pas jour dans le cache

R. Grin JPA page 243

Utilisation ou non du cache


Le fichier persistence.xml peut indiquer si une unit de persistance utilisera ou non un cache avec llment caching qui peut avoir 4 valeurs possibles : ALL, NONE, ENABLE_DELECTIVE et DISABLE_SELECTIVE Exemple :
<caching>ENABLE_SELECTIVE</caching>

Pas de valeur par dfaut ; il faut donc toujours donner une valeur pour avoir une application portable entre les fournisseurs de persistance
JPA page 244

R. Grin

Utilisation ou non du cache


ALL : un cache sera utilis pour toutes les entits NONE : aucun cache ne sera utilis ENABLE_SELECTIVE : par dfaut, les entits ne sont pas caches ; seules le sont celles qui sont annotes par @Cacheable(true) DISABLE_SELECTIVE : par dfaut, les entits sont caches ; seules ne le sont pas celles qui sont annotes par @Cacheable(false)

R. Grin JPA page 245

Annotation @Cacheable
Une classe dentits peut tre annote pour indiquer si les entits de la classe seront conserves dans le cache (voir lment caching de persistence.xml pour plus de prcisions) @Cacheable suffit car true est la valeur par dfaut Exemple :

@Entity @Cacheable(true) public class Pays { ... }

R. Grin

JPA

page 246

41

Interface Cache

Mthodes de linterface Cache


JPA 2 a introduit cette interface simplifie avec le cache pour affiner les indications donnes par @Cacheable

boolean contains(Class cls, Object clPrimaire) indique si le cache contient

Par exemple, pour une classe dentits cacheable , il est possible denlever une certaine entit du cache Si le cache nest pas utilis, les mthodes ne font rien, part contains qui renvoie toujours false

une entit

void evict(Class cls) enlve du cache

toutes les entits dune certaine classe


void evict(Class cls, Object clPrimaire) enlve du cache une certaine

entit

Le cache sobtient avec la mthode getCache() de EntityManagerFactory


JPA page 247

void evictAll() vide le cache

R. Grin

R. Grin

JPA

page 248

Proprits lies au cache


En plus de toutes les possibilits dj exposes, on peut donner des indications pour les mthodes find, refresh et pour les requtes (Query) excutes par un gestionnaire dentits (voir spcification pour plus de dtails) Exemple :

Proprits pour un find


Il est possible de donner des indications dutilisation du cache pour un seul find Exemple :
HashMap props = new HashMap(); props.put(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.BYPASS); em.find(MyEntity.class, id, props);

em.setProperty( QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);


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

Proprits pour les commit


Il est aussi possible dindiquer si les donnes valides par un commit seront mises dans le cache

Optimisations

R. Grin

JPA

page 251

R. Grin

JPA

page 252

42

Les performances dune application peuvent tre grandement amliores par n un choix adapt du mode de rcupration des entits associes n lutilisation doprations de modifications en volume, sans cration dentits me n une bonne utilisation du cache de 2 niveau

Mthode callback et listener

R. Grin

JPA

page 253

R. Grin

JPA

page 254

Mthodes callback
Des mthodes peuvent tre annotes pour indiquer quelles seront appeles par le fournisseur de persistance quand une entit passera dans une nouvelle tape de son cycle de vie Ces mthodes peuvent appartenir une classe entit (entity) ou classe mre mappedSuperclass ou une classe couteur (listener) Une mthode peut tre annote par plusieurs de ces annotations

R. Grin JPA page 255

Annotations
@PrePersist : quand persist (ou merge) sest termin avec succs @PostPersist : aprs linsertion dans la BD @PreRemove : quand remove est appel @PostRemove : aprs suppression dans la BD @PreUpdate : avant modification dans la BD @PostUpdate : aprs modification dans la BD @PostLoad : aprs la lecture des donnes de la BD pour construire une entit

R. Grin JPA page 256

Callback dans fichier XML


Les mthodes callback peuvent aussi tre indiques dans un fichier XML Un fichier XML peut aussi indiquer des listeners par dfaut qui seront appeles pour toutes les entits, dans le sous-lment <entity-listeners> de llment <persistence-unit-defaults>

Exemples dutilisation
Un trigger de la base de donnes peut donner les valeurs de lutilisateur qui a modifi pour la dernire fois une entit, avec la date de cette modification Pour remplacer un tel trigger, il est possible dajouter une mthode annote par @PrePersist qui remplit ces valeurs dans les entits Une mthode callback peut aussi initialiser des attributs non persistants dune entit
R. Grin JPA page 258

R. Grin

JPA

page 257

43

Callback dans une entit


Ces mthodes ne doivent aucune paramtre et le type retour doit tre void Elles ne doivent pas avoir de clause throws

Callback dans un couteur


La signature doit avoir un paramtre compatible avec le type de lentit gre pour quil puisse contenir linstance de lentit Compatible signifie que le type doit tre un surtype de la classe entit : la classe de lentit, ou une classe mre, ou une interface implmente par la classe de lentit Une classe listener ne doit contenir aucune variable dinstance (elle doit tre sans tat ) et doit avoir un constructeur sans paramtre
R. Grin JPA page 260

Si elles renvoient une exception non contrle, les ventuelles mthodes callbacks suivantes ne sont pas appeles et la transaction est marque pour un rollback (elle ne pourra pas tre valide) Une seule mthode callback dun certain type (par exemple PrePersist) par entit

R. Grin JPA page 259

Attacher un couteur
Lannotation @EntityListeners permet dattacher un ou plusieurs couteurs une classe entit Exemple :

Ordre dappel
Lorsque un vnement du cycle de vie survient, les diffrentes mthodes sont appeles dans cet ordre : 1. Mthodes des listeners par dfaut 2. Mthodes des listeners 3. Mthode de lentit en cause

@Entity @EntityListeners({C1.class, C2.class}) public class Entite {

R. Grin

JPA

page 261

R. Grin

JPA

page 262

Prsentation

Dans Java EE 6 la validation des donnes a t standardise (JSR 303)

Validation des donnes

La validation des donnes peut aussi tre utilise dans les applications en dehors de Java EE mais il faut alors ajouter un jar au classpath Des annotations permettent de dfinir des contraintes sur les donnes

R. Grin

JPA

page 263

R. Grin

JPA

page 264

44

Exemple
public class Employe { @NotNull private int id; @NotNull(message="Le nom doit tre donn") @Size(max=40) private String nom; @Past private Date dateEmbauche; ...

Validations standard (1/3)


@Null, @NotNull Pour toutes les contraintes suivantes, null est considr comme valide @AssertTrue, @AssertFalse : valeur boolenne impose (boolean ou Boolean) @Min, @Max : bornes pour un entier (long) ; tous les types de nombres sont supports, sauf double et float ( cause des erreurs darrondi) @DecimalMin, @DecimalMax : bornes pour une valeur dcimale (String)
R. Grin JPA page 266

R. Grin

JPA

page 265

Validations standard (2/3)


@Size avec les attributs min et max ; types supports : String, Collection, Map, tableau @Digits avec les attributs integer et fraction : nombres maximums de chiffres dans les parties entires et dcimales ; types supports : BigDecimal, String, tous les types entiers (int, Integer, byte,...), y compris BigInteger, mais pas les types double et float (erreurs darrondi)

R. Grin JPA page 267

Validations standard (3/3)


@Past, @Future : date avant ou aprs la date actuelle ; types supports : Date et Calendar du paquetage java.util @Pattern : la valeur correspond une expression rgulire ; lattribut flags peut comporter des valeurs utiles pour vrifier la concordance (voir javadoc de java.util.regex.Pattern) : UNIX_LINES, CASE_INSENSITIVE, MULTILINE,...

R. Grin JPA page 268

Validations particulires

Validation dans JPA


Il est possible dajouter des validations aux validations standard ; pas tudi dans ce cours

JPA 2 permet de valider les donnes automatiquement durant le cycle de vie dune entit, dans les phases pre-persist , preupdate et pre-remove , ce qui permet dconomiser lcriture dun couteur dont le rle ne serait que de valider des entits

R. Grin

JPA

page 269

R. Grin

JPA

page 270

45

Configuration
Il est possible de configurer le mode de validation (validation ou non) par llment <validation-mode> du fichier persistence.xml La valeur par dfaut est AUTO : validation si un fournisseur de persistance (jar) est dtect CALLBACK : un fournisseur de persistance doit tre prsent (sinon une exception est lance la cration dune fabrique de EM) NONE : pas de validation

R. Grin JPA page 271

Configuration
Par dfaut, les entits sont valides dans les phases pre-persist et pre-update pour le groupe de validation Default (voir API de validation) mais pas pour la phase pre-remove Il est aussi possible de configurer par une proprit passe la mthode createEntityManagerFactory (par exemple pour valider dans la phase pre-remove)

R. Grin

JPA

page 272

Exemple dentit
@Entity public class Client { @Id @NotNull private int id; @NotNull @Size(max=60) private String nom; @(groups=Remove.class,min=0,max=0) private int nbLivraisonsEnCours; ... }
R. Grin JPA page 273 R. Grin

Adaptation une base relationnelle prexistante

JPA

page 274

Position du problme
Parfois les structures des bases prexistantes ne respectent pas les bons usages ou ne correspondent pas aux valeurs par dfaut supposes par JPA, pour des raisons diverses Cest souvent le cas pour ce qui concerne la modlisation des associations entre entits En ce cas, il faut utiliser les annotations du type @JoinColumn

R. Grin JPA page 275

Un exemple
Les cas sont trs divers et ne peuvent tre couverts exhaustivement Nous allons voir un exemple dutilisation de lannotation @JoinColumn qui donne des informations sur une cl trangre

R. Grin

JPA

page 276

46

Un exemple les tables


Une table Groupe contient les colonnes id (cl primaire de type integer) et nom (de type varchar) ; une table Utilisateur contient les colonnes id (cl primaire de type integer), nom et nom_groupe (toutes les 2 de type varchar) Cette dernire colonne est une cl trangre vers la colonne nom de la table groupe (qui est une colonne unique : 2 groupes ne peuvent avoir le mme nom)

R. Grin JPA page 277

Un exemple les entits


public classe Groupe { @Id private long id; private String nom; @OneToMany(mappedBy="groupe") private Collection<User> users; } public classe Utilisateur { @Id private long id; private String nom; @ManyToOne private Groupe groupe; }
R. Grin JPA page 278

Un exemple le problme

Un exemple la solution

Si on laisse JPA gnrer un schma relationnel partir de ces entits, lassociation sera traduite par une cl trangre de type integer qui pointera vers lid de groupe et une cl trangre de type varchar qui pointe vers le nom, comme dans la base prexistante

Il faut complter lannotation @ManyToOne de la classe Utilisateur :


@ManyToOne @JoinColumn( name="nom_groupe", referencedColumnName="nom") private Groupe groupe;

JPA peut sadapter presque toutes les situations prexistantes ; il faut cependant parfois bien chercher dans la spcification avant de trouver la solution
JPA page 280

R. Grin

JPA

page 279

R. Grin

Gnration du schma

Prcisions pour la gnration du schma de la base de donnes


Tous les fournisseurs de persistance offrent la possibilit de gnrer automatiquement le schma de la base de donnes partir des classes entits Java (voir section prcdente pour le cas o la base existe dj) En ce cas, il est possible de donner des prcisions sur le schma gnr

R. Grin

JPA

page 281

R. Grin

JPA

page 282

47

Contrainte dunicit sur une colonne


Contrainte dunicit sur une table


@Column(unique=true)

Une contrainte dunicit sera ajoute dans la dfinition de la colonne de la table Comme dans toute cette section, lattribut unique ne servira rien (sinon pour la documentation du code) si le schma nest pas gnr automatiquement

@Table(uniqueConstraints = @UniqueConstraint( columnNames = {"COL1", "COL2"})) Une contrainte dunicit sera ajoute dans la dfinition de la table

R. Grin

JPA

page 283

R. Grin

JPA

page 284

Contraint NULL

Types de donnes

@Column(nullable=false) Une contrainte NOT NULL sera ajoute la dfinition de la colonne

@Column(length=25) prcise la taille de la colonne de type chane de caractres (longueur 255 par dfaut, ce qui est souvent beaucoup trop) @Column(precision=10, scale=2) prcise la prcision (le nombre total de chiffres) et le nombre de chiffres aprs la virgule pour une colonne de type nombre dcimal (float, double,)
R. Grin JPA page 286

R. Grin

JPA

page 285

Dfinition quelconque
On peut mme donner la dfinition du type dune colonne pour prendre en compte des particularits de certains SGBD Lattribut columnDefinition des annotations @Column, @JoinColumn, @PrimaryKeyJoinColumn, @DiscriminatorColumn permet de dfinir un type particulier Exemple :

Bibliographie

@Column(columnDefinition="NVARCHAR2(8)")
R. Grin JPA page 287 R. Grin JPA page 288

48

Sites Web
Spcification Eclipselink Hibernate

Livres

officielle de JPA 2 :

http://jcp.org/en/jsr/detail?id=317

http://www.eclipse.org/eclipselink/jpa.php

: http://www.hibernate.org/

Pro JPA 2: Mastering the Java Persistence API de Mike Keith et Merrick Schincariol Edition Apress (disponible la BU de Valrose)

Open JPA : http://openjpa.apache.org/

R. Grin

JPA

page 289

R. Grin

JPA

page 290

49