Download - Formation JPA Java persistence API
Auth
or: T
hiba
ult
Cuvi
llier
– C
reat
ive
Com
mon
s 2.
0
JP 1.1 - Template 1.0
Java Persistence API
Auteur: Thibault CuvillierConsultant indépendant
[email protected]://www.btcweb.com
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction
Contenu de la présentation
• Chap 1: Introduction• Chap 2: Mapping objet relationnel – Niveau 1• Chap 3: EntityManager• Chap 4: EJBQL – Niveau 1• Chap 5: Mapping objet relationnel – Niveau 2• Chap 6: EJBQL – Niveau 2
• Les questions et corrigés des TP sont accessibles sur mon site.
• JPA 1, TP avec Hibernate 3.1 et Eclipse (pas mavenifié…)
2
Auth
or: T
hiba
ult
Cuvi
llier
– C
reat
ive
Com
mon
s 2.
0
JP 1.1 - Template 1.0
javax.persistence
Introduction
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 4
Introduction à javax.persistence
Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 5
Accéder à la base de données
• Les objets d'une applicationpeuvent être:– Transitoires: ils ne survivent pas
à l'application– Persistants: ils survivent à l'application
• Exemple: dans un système devente en ligne:– La classe Caddie est transitoire,
ne contenant que des informations sur la session– La classe produit est persistante dans une base
de données.
Caddie
Session Http
Item
Produit
*
*
*1
1
1
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 6
Les quatre modèles 1/2
Le modèle conceptuelLa compréhension de l'utilisateur
Le modèle de présentationLes données présentées à l'utilisateur
Le modèle logiqueModèle objet
Le modèle physiqueSchéma de la base
transitoire
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 7
Les quatre modèles 2/2
• Les quatre modèles doivent être isomorphes– Intégration sémantique
• Les relations entre les modèles sont des mappings
• Mapping entre le modèle logique et le schéma d'une base de données relationnelle:– Mapping Objet Relationnel
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 8
Le mapping objet-relationnel
• Décrit la projection d'une classe dans un SGRBR• Exemple:
– Une classe = Une table– Une propriété = Une colonne
• Le mapping O/R est plus complique:– Comment projeter l'héritage ?– Comment projeter les relations entre objets ?– Comment projeter les types de données Java ?– …
• Il y a de nombreuses conceptions possibles…Suite
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 9
API de persistance avec JDBC / DAO 1/2
• Les objets persistants sont des JavaBeans• Vous y accédez via des DAO
– Data Access Object• Implémente les méthodes de persistance:
– Insérer, détruire, modifier, requêtes…
PersonnePersonneDAO
prenomnomemail
insererdétruiremodifierrequete(prenom, nom)
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 10
API de persistance avec JDBC/DAO 2/2
• La couche de persistance prend en charge le mapping O/R– Hard-codé en Java, Séparé des données
• Mais:– Un objet peut être chargé deux fois en mémoire– La navigation entre objets est délicate à gérer– Les objets ne sont stockés en cache, générant un
flux important de requêtes SQL
PersistanceApplication Mapping O/RPOJO
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 11
Cache de persistance
• L'ajout d'un cache permet:– De limiter le nombre de requêtes SQL– De ne conserver en mémoire qu'un seul
exemplaire des objets persistants
• Mais, comment gérer les transactions ?
PersistanceApplication Mapping O/RCachePOJO
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 12
Cache transactionnel
• Le cache doit être transactionnel– Isolation transactionnelle– Consistance
• Il doit être multi-thread safe
• Cette solution est complexe
Persistance
ApplicationMapping O/RCachePOJO
Gestion des transactionsGestion de la sécurité
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 13
Outils de mapping O/R• Moteur de mapping générique
– utilise une description du mapping• Cache transactionnel• Les objets persistants sont
des POJOs• Un DAO générique
Persistance
ApplicationMapping O/RCacheAPI
Gestion des transactionsGestion de la sécurité
Descriptiondu mapping O/R
mapping.xml
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 14
Mapping objet relationnel
• Produits de mapping objet / relationnels– Hibernate, JDO, Toplink (Oracle)
• Ces produits savent:– Mapper une classe sur plusieurs tables,– Mapper des objets dépendants,– Mapper types complexes,– Mapper des relations,– Mapper l'héritage entre entités,– Gérer des caches locaux ou distribués.
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 15
Exemple Hibernate 1/2Client.hbm.xml
<hibernate-mapping>
<class name="com.btc.Client" table="CLIENT"> <property name="prénom"> <column name="PRENOM" length="32"/> </property> … </class></hibernate-mapping>
Adresse
ruevillecodePostal
1
0..*
<<Tables>>CLIENT
ID
PRENOM
<<Table>>EMAIL
CLIENT_FK
<<Entity>>Client
idprénomnomtéléphone NOM
TELEPHONE
RUE
VILLE
CODEPOSTAL
Tables
Mapping O/RPOJO
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 16
Exemple Hibernate 2/2
• Le code client devient simple et naturel:Session session = … ouvrir la session Hibernate …;
Transaction tx = session.beginTransaction();
tx.begin();Client client = new Client();
client.setPrénom("Bill");client.setNom("Gates");
Adresse adresse = new Adresse("5 rue de l'église", "Lyon", "69002");client.setAdresse(addresse);client.addEMail("[email protected]");client.addEMail("[email protected]");
session.save(client);tx.commit();session.close();
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 17
javax.persistence
• Nouvelle API Java de persistance– Implémentations avec Hibernate, JDO, Toplink ou
autre– J2EE (module EJB ou Web) ou J2SE
• package javax.persistence– Fonctionne avec J2SE et J2EE
• Contexte de persistance:– Gère le cache des objets– Transactionnel– Durée de vie: TRANSACTION ou EXTENDED– Une application peut utiliser plusieurs contextes
PersistenceContext
PersistenceContext
PersistenceContext
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 18
Entités• Interface unifiée• Le descripteur de mapping O/R standard
– Peut être généré à partir d'annotations Java5.@Entitypublic class Client extends Serializable { private long _id; private String _nom;
@Id public long getId() { return _id; } public void setId(long id) { _id = id; }
public String getNom() { return _nom; } public void setNom(String nom) { _nom = nom; } …
}
Cette entité est complète !
<<Tables>>CLIENT
ID
NOM
Mapping par défaut
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 19
Non Géré
Cycle de vie des Entités
Transitoire
Détaché
persistcascade
merge
sérialisationfin de TX
Etat Dans la base Associé à un contexte de persistance
Transitoire
Non Non
Existe Oui OuiDétaché Oui NonDétruit Non Oui
findquery EJBQL
Géré dans un contexte
Existe
Détruit
• Gérée = associée à un contexte de persistance
persist
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 20
Avantages des Entités
• Objets persistants de faible granularité– Plus proche du modèle d'analyse
• Mapping O/R puissant• Fonctionne avec J2EE et J2SE• Langage de Query: EJBQL• Accès direct à la connexion sous jacente
– Pour optimisations– Pour utiliser des API spécifiques (Hibernate, JDO)
• Permet de générer le schéma de la base à partir des annotations (pas recommandé)
JP 1.1 - Template 1.0
Auth
or: T
hiba
ult
Cuvi
llier
– C
reat
ive
Com
mon
s 2.
0
javax.persistence
Mapping Objet / RelationnelNiveau 1
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 22
Mapping OR
Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 23
Mapping O/R > Mapping simple
• Mapping O/RMapping simpleIdentité simpleCallback
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 24
Classe persistante
• Doit être annotée avec @Entity
– nameNom de l'entité utilisé dans les expressions EJBQLselect c from Compte c where c.solde < 0
– accessAnnotation des attributs persistants sur le getter (PROPERTY, par défaut) ou sur les attributs (FIELD) qui ne doivent pas être privés (à éviter!).
• Doit avoir un constructeur par défaut
@Entity(name="Compte" access=AccessType.PROPERTY)
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 25
Mapping 1 classe / 1 table 1/3• Annotation @Table
– name : Nom de la table, nom de la classe.– catalog : Catalogue de la table, celui de la ctx.– schema: Schéma de la table, celui de la ctx.
• Pour générer le schéma:– UniqueContraint uniqueContraints[]
Contraintes d'unicité simples ou composites– Annotation @UniqueContraint
•columnNames: colonnes dans la contrainte
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 26
Mapping 1 classe / 1 table 2/3
• Table: <schéma pardéfaut>.Client
• Table: <schéma pardéfaut>.CLIENT_TBL
• Table: FORMATION.CLIENT_TBL
@Entitypublic class Client implements Serializable { … }
@Entity@Table(name="CLIENT_TBL")public class Client implements Serializable { … }
@Entity@Table(name="CLIENT_TBL", schema="FORMATION")public class Client implements Serializable { … }
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 27
Mapping 1 classe / 1 table 3/3
• Table FORMATION.CLIENT_TBL + contrainte d'unicité sur (prenom, nom) et (telephone)
@Entity@Table(
name="CLIENT_TBL",uniqueConstraints={@UniqueConstraint(columnNames={"nom",
"prenom"}),@UniqueConstraint(columnNames={"telephone"})})public class Client implements Serializable { … }
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 28
Propriétés persistantes 1/2
• Doit avoir un des types suivants:– Type primaire Java: int, long, double …– String, BigInteger, BigDecimal, Date, Calendar,
Date…– byte[], Byte[], char[], Character[]– enums Java5 (colonne integer ou String)– Classe Java sérializable (a éviter, voir + loin)– Classe Java dépendante (voir + loin)– Collection, Set, List, Map ou génériques List<T>…
•Type de base, Entités.– Attention, les types de base ne peuvent être NULL
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 29
Propriétés persistantes 2/2
• Déclarez les accesseurs public:– T getX() et void setX(T t)– boolean isX() et void setX(boolean b)
• Peuvent ou non être déclarés dans l'interface• Ne doivent pas exécuter de logique métier• Si une exception est levée dans getX ou setX,
la transaction rollback.
• Attributs non persistant:
private transient String _pwdDecrypté;@Transientpublic String getPwdDecrypté() {…}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 30
@Basic, @Temporal
• Indique un mapping simple pour une propriété persistante– Par défaut, toutes les propriétés sont persistantes
• @Basic– fetch = EAGER ou LAZY– optional =
true ou false• @Temporal
– value = TIMESTAMP ,DATE, TIME
@Basic@Temporal(TemporalType.DATE}public Date getDateNaissance() { return _ddn;}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 31
Mapping 1 propriété / 1 colonne 1/3
• Utilisez l'annotation @Column– name: Nom de la colonne - Nom de la propriété– insertable: utilisée dans INSERT? - true– updatable: utilisée dans UPDATE? - true
• Pour pouvoir générer le schéma:– nullable: peut être NULL? - true– unique: Valeur est unique dans la table - false– columnDefinition - Définition SQL de la colonne– length: longueur de la column - 255– precision, scale pour les colonnes numérique - 0
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 32
Mapping 1 propriété / 1 colonne 1/3
• Colonne "NOM"VARCHAR(255)
• Colonne "NAME"VARCHAR(32)
• Colonne "NAME"VARCHAR(32)NOT NULL
private String _nom;public String getNom() { return _nom; }public void setNom(String nom) { _nom = nom; }private String _nom;@Column(name="NAME", length=32)public String getNom() { return _nom; }public void setNom(String nom) { _nom = nom; }private String _nom;@Column(name="NAME", length=32, nullable=false)public String getNom() { return _nom; }public void setNom(String nom) { _nom = nom; }
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 33
Mapping 1 propriété / 1 colonne 3/3
• Colonne "DESC"CLOB
• Colonne "TIME"TIMESTAMP
• Colonne "SOLDE"Non modifiable
private String _desc;@Column(columnDescription="CLOB")public String getDesc() { return _desc; }public void setDesc(String desc) { _desc = desc; }
private Time _time;@Column(columnDescription="TIMESTAMP")public Time getTime() { return _time; }public void setTime(Time time) { _time = time; }
private double _solde;@Column(precision=12, updatable="false")public double getSolde() { return _solde; }public void setSolde(double solde) { _solde = solde; }
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 34
Mapping O/R > Identité simple
• Mapping O/RMapping simpleIdentité simpleCallback
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 35
Identité
• L'identité d'une Entité = Clef Primaire• Identité métier:
– Identité simple = Une seule valeur– Identité composite = Plusieurs valeurs
• Identité technique: une colonne neutre– Entier long– Séquence Oracle, Colonne automatique MySQL…
L'identité d'une entité doit être invariable.!
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 36
Recommandations
• N'utilisez que des Identificateurs neutres– Long ou long– Initialisation: séquence, table de compteurs,
colonnes à incrémentation automatique…• Ajoutez si nécessaire des colonnes pour
améliorer la performance des requêtes<<Table>> Client
idnomprénomtéléphonesociétéId
<<Table>> Facture
idclientIdsociétéIdmontantHTmontantTTCtva
<<Table>> Soctété
idnom
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 37
Identité simple 1/4
• La propriété contenant l'identité: @Id• Pour une identité technique générée:• @GeneratedValue
– strategyNONE: pas de génération - Valeur par défautTABLE: utilisation d'une table pour gérer les IDSEQUENCE: utilisation de séquences (Oracle par ex.)IDENTITY: génération de la valeur par la baseAUTO: génération par le fournisseur de persistance
– String generator (Si generate != NONE)Nom du générateur
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 38
Identité simple 2/4
• La valeur de l'IDest contrôlée par l'application
• La valeur de l'IDest fixée lorsd'un INSERT parune séquence.
@Idpublic long getId() { return _id; }
@Id@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CLIENT_ID_SEQ")@SequenceGenerator( name="CLIENT_ID_SEQ", sequenceName="CLIENT_ID", initialValue=0, allocationSize=50)public long getId() { return _id; }
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 39
Identité simple 3/4
• Les ID sont générés à partir de la table IDGEN possédant une colonne ID_KEY (PK), ID_VAL.
• La valeur de l'ID suivant utilise la clef "CLIENT_ID".
@Id@GeneratedValue( strategy=GenerationType.TABLE, generator="CLIENT_ID_TBL")@TableGenerator( name="CLIENT_ID_TBL", table="IDGEN", pkColumnName="ID_KEY", valueColumnName="ID_VAL", pkColumnValue="CLIENT_ID", initialValue=1, allocationSize=25)public long getId() { return _id; }
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 40
Identité simple 4/4
• La valeur de l'ID est générée par la base, par une colonne à incrémentation automatique
• Colonne Automatic MySQL, Identity HsQL@Id@GeneratedValue(strategy=GenerationType.IDENTITY)public long getId() { return _id;}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 41
Mapping O/R > Callbacks
• Mapping O/RMapping simpleIdentité simpleCallback
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 42
Callbacks
• Méthodes déclenchéespour notifier leschangements d'étatsd'une entité
@Entitypublic class Login { private String password; private String cryptedPassword;
@PrePersist @PreUpdate public void preUpdate() { cryptedPassword = crypt(password); }
@PostLoad public void postLoad() { password = decrypt(cryptedPassword); } …}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 43
Callbacks des entités
• @PrePersist et @PostPersist– Appelé avant et après EntityManager.persist()
• @PreRemove et @PostRemove– Appelé avant et après EntityManager.remove()
• @PreUpdate et @PostUpdate– Appelé avant et après une maj dans la base
• @PostLoad– Appelé après le chargement de l'entité
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 44
Listener d'entité• Vous pouvez mettre le code des callbacks
dans un listener avec @EntityListener.
@Entity@EntityListener(com.btc.LogListener)public class Personne { …}
public class LogListener { @PrePersist public void prePersist(Object o) { System.out.println("PrePersit(o=" + o+")"); }}
Personne.java
LogListener.java
L'entité est passée en paramètre!
Les listeners sont hérités !!
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 45
Travaux pratiques
• Ouvrez le projet JP-Lab01-Mapping-Question– Suivez les instructions
JP 1.1 - Template 1.0
Auth
or: T
hiba
ult
Cuvi
llier
– C
reat
ive
Com
mon
s 2.
0
javax.persistence
EntityManager
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 47
EntityManager
Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 48
EntityManager
• Permet de changer l'état persistant des entités– Création, destruction, modification
• Associé à un contexte de persistance• Permet d'exécuter des requêtes
– EJBQL: select c from client c where c.nom=:nom– Permet de fermer le contexte de persistance
(J2SE)– Permet de contrôler les transactions (J2SE ou pas
JTA)
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 49
Création d'un EntityManager avec J2SE
• L'EntityManager est créé par unefactory
• La factory contient la description du mapping
• Vous pouvez utiliser plusieurs contextes de persistance dans votre application– Une factory par contexte de persistence
Attention, différent pour un serveur J2EE
EntityManagerFactory factory = Persistence.createEntityManagerFactory("em", new Properties());
EntityManager em = factory.createEntityManager();
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 50
persistence.xml
• La factory est décrite dans le fichierMETA-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8"?><persistence> <persistence-unit name="em" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.password" value="root"/> <property name="hibernate.connection.url" value="jdbc:mysql://127.0.0.1/db"/> </properties> </persistence-unit></persistence>
Transactions:•RESOURCE_LOCAL•JTA
Attention avec un serveur J2EE, utilisation de JNDI et de JTA
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 51
TRANSACTION et EXTENDED 1/2
• Le contexte de persistance maintient les données en cache.
• Le cache peut avoir deux durées de vie:– TRANSACTION
Les caches sont vidés à la fin de chaque transaction– EXTENDED
Les caches sont vidés lorsque le contexte est fermé• Le cache peut être paramétré
– Annotations et paramétrage XML non standard– Dépend de l'implémentation
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 52
TRANSACTION et EXTENDED 2/2
• Pour créer un EntityManager EXTENDED:
• Il est préférable d'utiliser des caches transactionnels et de reposer ainsi sur l'isolation transactionnelle de la base
EntityManagerFactory factory = Persistence.createEntityManagerFactory("em", new Properties());
EntityManager em = _factory.createEntityManager(PersistenceContextType.EXTENDED);
…em.close();
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 53
EntityManager.find
• EntityManager.find(Class c, Object id)– Charge un objet en mémoire et le retourne
• EntityManager.getReference(Class c, Object id)– Ne charge pas l'objet en mémoire, ne contient
que l'ID.– L'état sera chargé lors du premier accès à une
propriété persistanteEntityManager em = … on verra plus loin …;Client client = em.getReference(Client.class, "Bill Gates");em.remove(client);
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 54
Gérer les transactions
• Pas de transactionsimbriquées
• S'il n'y a pas de transaction,le contexte de persistance,la méthode find:– en commence une– la termine à la fin de la
méthode– retourne une entité détachée
• Pour modifier les données dans la base, il suffit de modifier un objet géré
EntityManager em = …;EntityTransaction tx = em.getTransaction();tx.begin();
try { … modifier les données … tx.commit();} catch(Exception e) { tx.rollback(); throw e;}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 55
EntityManager.persist 1/2
• void persist(Object entity)
– (1) Cascade sur les entités référencées si cascade=PERSIST ou ALL
Etat ActionTransitoire
Insertion dans la base (1)
Géré Rien sur l'entité(1)Détaché IllegalArgumentExceptionDétruit L'entité redevient managée (1)
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 56
EntityManager.persist 2/2
EntityManager em = …;EntityTransaction tx = em.getTransaction();tx.begin();Client client = new Client();client.setPrénom("Harry");client.setNom("Cover");client.setTéléphone("0404040404");em.persist(client);tx.commit();System.out.println("Client id = " + client.getId());
• Exemple:
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 57
EntityManager.remove
• void remove(Object entity)
– (1) Cascade sur les entités référencées si cascade=REMOVE ou ALL
Etat ActionTransitoire Rien sur l'entité, mais cascade (1)Géré Destruction de l'entité et cascade (1)Détaché IllegalArgumentExceptionDétruit Rien
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 58
EntityManager.merge
• <T> T merge(T entity)– Retourne une nouvel
entité géré
– (1) Cascade sur les entités référencées si cascade=MERGE ou ALL
Etat ActionTransitoire Création de l'entité (1)Géré Rien sur l'entité (1)Détaché Copie de l'état dans une entité gérée
avec la même identité (1)Détruit IllegalArgumentException
Attention, avec Hibernate, provoque une lecture de l'objet pour comparer son état.
!
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 59
EntityManager.merge: exemple
• La méthode fetch retourne l'objet persistant et le rend détache du contexte de persistance.
• La méthode save met à jour l'objet dans le contexte de persistance.
• fetch et save sont des méthodes transactionnellespublic Client fetchClient(long idclient) { EntityManager em = …; return em.find(Client.class, idclient);}public void saveClient(Client client) { EntityManager em = …; em.merge(client);}
Ne pas utiliser getReference: pourquoi ?
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 60
Objets détachés
• Un objet persistant devient détaché quand:– Le contexte de persistance se termine:
• TRANSACTION: Fin de la transaction • EXTENDED: Fermeture explicite du contexte
– Quand l'objet est sérialisé• Passage par valeur pour les interfaces Remote
– Quand l'objet est clonéWeb EJB Session
Client c = fetchClient("Bill Gates")
saveClient(c)
GET EditClient.jsp
POST EditClient.jsp
Navigateur Base
SELECT
UPDATE
findmerge
EntityManager
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 61
Transactions optimistes 1/2
• Un objet peut être modifié entre sa lecture et son merge par une autre requête– La dernière écriture gagne
• Transaction longue– Gestion pessimiste: vous devez gérer le verrouillage– Gestion optimiste: vous ajoutez une propriété Version
• La version est incrémentée à chaque modification– Lors du merge, le contexte de persistance vérifie si le
numéro de version a changé.– Exception dans ce cas, et rollback de la transaction
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 62
Transactions optimistes 2/2
• Il faut identifier la propriété contenant le numéro de version avec @Version– Peut être du type: int, Integer, long, Long, short,
Short, Timestamppublic Person { private long _version; @Version public long getVersion() { return _version; }}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 63
Mise à jour de la base de données
• La base de donnée est mise à jour lors du commit ou avant l'exécution d'une query
• Pour forcer la mise à jour:– EntityManager.flush()– Exécute le SQL
• Vous pouvez recharger l'état d'un objet modifié à partir de la base:– EntityManager.refresh(Objet o)– Annule les modifications apportées
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 64
Travaux pratiques
• Ouvrez le projet JP-Lab02-EntityManager-Question– Suivez les instructions
JP 1.1 - Template 1.0
Auth
or: T
hiba
ult
Cuvi
llier
– C
reat
ive
Com
mon
s 2.
0
javax.persistence
EJBQLNiveau 1
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 66
EJBQL
Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 67
Queries EJBQL simples
• EJBQL permet d'exécuter des requêtes– Pour lire des données– De faire des UPDATE et DELETE en masse
• Utilise le nom des entités et des propriétés– Pas le nom des tables et colonnes– Attribut name de l'annotation @Entity– Abstract Schema Name
select c from Client c where c.name="Alonso Bistrot"
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 68
La clause SELECT
• SELECT c from Client c– Retourne tous les clients
• SELECT c.name, c.email from Client c– Retourne le noms et l'email de tous les clients
• SELECT COUNT(c) from Client c– Retourne le nombre de clients
• SELECT AVG(c.age) from Client c– Retourne l'age moyen des clients– Autres fonctions: SUM, MIN, MAX
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 69
DISTINCT, ORDER BY, NEW
• Select DISTINCT c.name from Client c– Retourne une liste de nom unique
• Select c from Client c order by c.name ASC– Retourne la liste des clients triés par ordre alpha.– Ascendant: ASC (par défaut), Descendant: DESC
• Permet de retourner une liste d'objets Java quelconque– Pas forcément des entitésselect new com.btc.EmployeInfo(e.id, e.status, e.salaire) from Employe e
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 70
Opérateurs de la clause WHERE 1/2
• [NOT] BETWEEN– WHERE c.age BETWEEN 0 and 17– Equivalent à: c.age >= 0 AND c.age <= 17
• [NOT] LIKE– select c from Client c where c.name LIKE 'B%'– select c from Client c where c.name LIKE 'B_ _ _'
• [NOT] IN– select c from Commande c where c.status IN('E', 'A',
'B')• IS [NOT] NULL
– select c from Client c where c.status IS NULL
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 71
Fonctions EJBQL• CONCAT("a", "b") => "ab"• TRIM([BOTH, " ", ]" a ") => "a"
– 1er argument: BOTH, LEADING, TRAILING• LOWER("A") => "a"• UPPER("a") => "A"• LOCATE("ababab", "b" [, 3]) => 4• LENGTH("abcd") => 4• SUBSTRING("abcde", 2, 3) => "bcd"• ABS(-2) => 2• SQRT(4) => 2• MOD(101, 10) => 1• SIZE(c.commandes)
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 72
Opérateurs de la clause WHERE 3
• EXISTS– Vrai si la sous-requête retourne au moins un objet
• ALL, ANY (ou SOME)– ALL: Vrai si toutes les valeurs remplissent la
condition– ANY: Vrai si une valeur au moins remplie la
condition
SELECT DISTINCT emp FROM Employee emp WHERE EXISTS ( SELECT spouseEmp FROM Employee spouseEmp WHERE spouseEmp = emp.spouse)
SELECT emp FROM Employee emp WHERE emp.salary > ALL ( SELECT m.salary FROM Manager m WHERE m.department = emp.department)
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 73
GROUP BY
• GROUP BY permet de regrouperles valeurs retournées parla requête
• Requête sans clause GROUP BY:
• Requête avec la clause GROUP BY:
select v.entreprise, SUM(v.montant) from Vente v
Entreprise
MontantSUN 5500
IBM 4500SUN 7100
Entreprise
Montant
SUN 17100IBM 17100SUN 17100
Entreprise
Montant
IBM 4500SUN 12600
select v.entreprise, SUM(v.montant) from Vente v group by c.entreprise
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 74
HAVING
• Permet de tester des valeurs agrégées– Impossible dans une clause WHERE
select v.entreprise, SUM(v.montant) from Vente v group by v.entreprise having sum(v.montant) > 10000
Entreprise
Montant
SUN 12600
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 75
DELETE et UPDATE
• Permet de déclencher des delete et update de masse dans un batch.
• DELETE:• UPDATE:
• Le contexte de persistance n'est pas mis à jour• Utiliser:
– Dans une transaction séparée– Au début d'une nouvelle transaction
delete from Client c where c.status = 0update Employe c set c.salary = 1500 where c.salary < 1500
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 76
Exécuter une requête simples
• Les requêtes simples
• Avec des paramètres
public List findClients(EntityManager em) { Query query = em.createQuery("select c from Client c"); return query.getResultList();}
public List findClientsParStatus(EntityManager em, int status) { Query query = em.createQuery("select c from Client c where c.status = :status"); query.setParameter("status", status); return query.getResultList();}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 77
Requêtes nommées
• Déclarer les requêtes dans une annotation@NamedQueries( @NamedQuery( name="getByName", query="select e from Entreprise where name=:name"), @NamedQuery(name="getAll", query="select e from Entreprise"))public class EntrepriseMgr { public List<Entreprise> getEntreprises() { Query query = _em.createNamedQuery("getAll"); return query.getResultList(); }}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 78
Utiliser le SQL natif
• Vous pouvez utiliser des requêtes SQL
• Vous pouvez utiliser @NamedNativeQuery
public List getClients() { Query query = _em.createNativeQuery("select * from client", Client.class); return query.getResultList();}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 79
Mapping d'un ResultSet
• Vous pouvez mapper chaque colonne sur une ou plusieurs classes– Pas forcément des entités@SqlResultSetMapping(
name="getClientsSummariesResults", entities=@EntityResult(entityClass=com.valtech.ClientSummary, fields={ FieldResult(name="id" column="client_id"), FieldResult(name="name" column="client_name") }))public List getClientSummaries() { return _em.createNativeQuery( "select c.id as client_id, c.name as client_name from client c", " getClientsSummariesResults "). getResultList();}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 80
Travaux pratiques
• Ouvrez le projet JP-Lab03-EJBQL-Question– Suivez les instructions
JP 1.1 - Template 1.0
Auth
or: T
hiba
ult
Cuvi
llier
– C
reat
ive
Com
mon
s 2.
0
javax.persistence
Mapping O/RNiveau 2
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 82
Mapping avancé
Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 83
Mapping des relations
Mapping avancéMapping des relationsMapping de l'héritageAutres mappings
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 84
Relations entre Entités
• Support des relations 1-1, 1-n, n-m• Les relations peuvent uni ou bidirectionnelles• Certaines opérations peuvent se propager au
travers des relations– Cascade: remove, persist, merge …– Que sur les relations
OneToOne ou OneToMany Commande
Ligne1 Ligne2 Ligne3
remove
remove remove remove
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 85
Relation 1-1
@Entitypublic class Personne { private long _id; private Login _login;
@OneToOne public Login getLogin() { return _login; } public void setLogin(Login login) { _login = login; }}
@Entitypublic class Login { private Personne _personne; private String _login; private Stirng _password;
@OneToOne(mappedBy="login") public Personne getPersonne() { return _personne; } public void setPersonne(Personne p) { _personne = p; }}
Map sur la table PERSONNEPropriétaire de la relation Map sur la table LOGIN
Map sur lacolonne ID
PERSONNE contient une FK sur LOGINcolonne = <Propriété>_<column PK> = LOGIN_ID
Optionnel si la relation est
unidirectionnelle
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 86
Annotation OneToOne
• @OneToOne– (O) String mappedBy = ""
Propriété propriétaire de la relation– (O) boolean optional = true
Peut ou non être null– (O) targetEntity = type de la propriété
Le type de l'entité référencée– (O) CascadeType [] cascade = {}
Opérations à cascader au travers de la relation: ALL, PERSIST, REMOVE, REFRESH
– (O) fetchType fetch = EAGERAccès aux entités en mode LAZY ou EAGER
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 87
Fetch des entités
• EAGER:– Les objets liés sont chargés en une seule requête SQL
• LAZY:– Chargement de l'identité– Chargement de l'état lors du premier accès
EntityManager1 find(Personne.class, id)
EntityManager
Personne
1 find(Personne.class, id)
2 getLogin()LoginPersonne
2 getLogin()Login
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 88
Relation 1-n
@Entitypublic class Login { private long _id; private Role _role;
@ManyToOne public Role getRole() { return _role; } public void setRole(Role r) { _role = r; }}
@Entitypublic class Role { private long _id; private List<Login> _logins;
@OneToMany(mappedBy="role") public List<Login> getLogins() { return _logins; } public void setLogins(List<logins> l) { _logins = l; }}
Map sur la table LOGINPropriétaire de la relation
Map sur lacolonne ID
LOGIN contient une FK sur ROLEcolonne = <Propriété>_<column PK> = ROLE_ID
Optionnel si la relation est
unidirectionnelle
Map sur la table ROLE
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 89
Intégrité des relations
• C'est au développeur d'assurer l'intégrité des relations– Positionner la relation inverse– Lors du chargement, le lien
inverse est positionnéautomatiquement
• Une relation est mise à jour dans la base à partir de son propriétaire
Login login = new Login();Person person = new Person();login.setPerson(person);person.setLogin(login);
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 90
Annotations ManyToOne et OneToMany
• ManyToOne: même attributs que OneToOne• OneToMany: même attributs que OneToOne
– Sauf fetch qui vaut LAZY• Avec les collections génériques:
• Avec les collections non génériques:
@OneToMany(mappedBy="role") List<Personne> getPersonnes() {…}
@OneToMany(targetEntity=Personne.class, mappedBy="role")List getPersonnes() {…}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 91
Relation n-m
@Entitypublic class Role { private long _id; private List<Authorization> _authorizations; @ManyToMany public List<Authorization> getAuthorizations() { return _authorizations; } public void setAuthorization(List<Authorization> a) { _authorizations = a; }}
@Entitypublic class Authorization { private long _id; private List<Role> _roles;
@ManyToMany(mappedBy="authorizations") public List<Role> getRoles() { return _roles; } public void setRoles(List<Role> r) { _roles = r; }}
Map sur la table ROLEPropriétaire de la relation
Table d'association: ROLE_AUTORIZATIONSPK: ROLE_ID
PK: AUTHORIZATIONS_ID
Optionnel si la relation est
unidirectionnelle
Map sur la table AUTHORIZATION
Map sur lacolonne ID
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 92
Mapping d'une clé étrangère 1/2
@Entitypublic class Login { private long _id; private Role _role; @ManyToOne @JoinColumn( name="ROLE_FK") public Role getRole() { return _role; }}
@Entitypublic class Entreprise { private long _id; private Personne _pdg; @ManyToOne @JoinColumns( { @JoinColumn(name="PDG_FIRST_NAME_PK", referencedColumnName="FIRST_NAME"), @JoinColumn(name="PDG_LAST_NAME_PK") referencedColumnName="FIRST_NAME"), }) public Personne getPDG() { return _pdg; }}
Jointure simple
Jointure composite
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 93
Mapping d'une clé étrangère 2/2• @JoinColumn
– (O) String nameNom de la colonne contenant la clef étrangère.Par défaut: <Propriété du référant>_<PK du référé>
– (O) String referencedColumnNameClef primaire dans la table du référencé
– (O) boolean unique = false– (O) boolean nullable = true– (O) insertable = true– (O) updatable = true– (O) columnDefinition– (O) secondaryTable (on verra plus loin)
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 94
Mapping d'une table d'association
• @JoinTable permet de préciser le nom de la table d'association
@ManyToOne@JoinTable( name="ENTREPRISE_PDG", joinColumns = @JoinColumn(name="PDG_FK", referencedColumnName="ID"), inverseJoinColumns = @JoinColumn(name="ENT_FK", referencedColumnName="ID")) public Personne getPDG() { return _pdg; }}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 95
Mapper une HashMap
• Permet de mapper la valeur des clefs d'une Map– @MapKey: name contient le nom de la propriété
persistante qui formera la clef– Par défaut: la clef primaire
@OneToMany@MapKey(name="id") public Map<PersonneID, Personne> getEmployés() { return _employés; }
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 96
Ordre des relations
• Permet d'ordonner les objets liés en fonction d'un ou plusieurs propriétés.
• @OrderBy– Par défaut: la PK ASC
@Entitypublic class Role { @Id long _id; private List<Login> _logins;
@OneToMany(mappedBy="role") @OrderBy("user ASC") public List<Login> getLogins() { return _logins; } public void setLogins(List<logins> l) { _logins = l; }}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 97
BLOB et CLOB
• Permet de préciser le type d'une colonne contenant un Large OBject– Propriété String
CLOB: données texte– Autre type de donnée
BLOB: données binaires• fetch: EAGER ou
LAZY
@Entitypublic class Role { private JPEGImage _image; @Lob @Basic(fetch=FetchType.LAZY) public JPEGImage getPhoto() { return _image; }}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 98
Travaux pratiques
• Ouvrez le projet JP-Lab04-Relation-Question– Suivez les instructions
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 99
Mapping de l'héritage
Mapping avancéMapping des relationsMapping de l'héritageAutres mappings
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 100
Héritage
• Une entité peut hériter d'une autre entité– Héritage des propriétés– Héritage des relations– Requêtes EJBQL polymorphes
• Une entité peut être abstraite– Jamais instanciée– Possède un mapping O/R– Peut faire la cible de requêtes polymorphes
• Une entité peut hériter d'une classe Java qui n'est pas une entité
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 101
Une table par hiérarchie
• Une colonne donne le type de l'objet:– Le discriminant
• Requête polymorphe:– select v from Voiture v
where v.couleur ='rouge'
Voiture
idcouleur
toit=capote, hardtop
Berline Cabriolet
barresDeToit
disc id couleur barresDeToit toit
Personnepropriétaire0..n 1
proprietaire
VOITURE
Attention, toutes les propriétés doivent
être nullable.
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 102
Une table par hiérarchie: exemple
• Chaque sous classe doit utiliser une valeur différente du discriminateur
@Entity@Inheritance( strategy=SINGLE_TABLE)@DiscriminatorColumn(discriminatorType=STRING) public abstract class Voiture { @Id long _id; private Personne _propriétaire; private String _couleur; …}
@Entity@DiscriminatorValue("B")public class Berline extends Voiture { private boolean barresDeToit;}
@Entity@DiscriminatorValue("C")public class Cabriolet extends Voiture { public enum Toit {HARDTOP, CAPOTE}; private Toit _toit;}
STRING, CHAR, INTEGER
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 103
Une table par classe concrète
• Consomme peu de place disque
• Requêtes polymorphes coûteuses
idcouleur
toit=capote, hardtopbarresDeToit
propriétaire0..n 1
id couleur barresDeToit toitproprietaire id couleur proprietaire
CABRIOLETBERLINE
Voiture
Berline Cabriolet
Personne
Le support de ce mapping est optionnel
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 104
Une table par classe concrète: exemple@Entity@Inheritance(strategy=TABLE_PER_CLASS)public abstract class Voiture { @Id long _id; private Personne _propriétaire; private String _couleur; …}@Entitypublic class Berline extends Voiture { private boolean barresDeToit;}
@Entitypublic class Cabriolet extends Voiture { public enum Toit {HARDTOP, CAPOTE}; private Toit _toit;}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 105
Une table par classe
• Proche du modèle objet
• Performance des requêtes
idcouleur
toit=capote, hardtopbarresDeToit
propriétaire0..n 1
id barresDeToit toitid
id couleur proprietaire
Voiture
Berline Cabriolet
Personne
BERLINE CABRIOLET
VOITURE
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 106
Une table par classe: exemple
• Les sous classes contiennent une FK sur la classe de base
• Peut être renommée avec@PrimaryKeyJoinColumn
@Entity@Inheritance(strategy=JOINED)public abstract class Voiture { @Id long _id; private Personne _propriétaire; private String _couleur; …}@Entitypublic class Berline extends Voiture { private boolean barresDeToit;}
@Entitypublic class Cabriolet extends Voiture { public enum Toit {HARDTOP, CAPOTE}; private Toit _toit;}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 107
Travaux pratiques
• Ouvrez le projet JP-Lab05-Inheritance-Question– Suivez les instructions
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 108
Autres mappings
Mapping avancéMapping des relationsMapping de l'héritageAutres mappings
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 109
Les classes embedded
• Classe Java contenant une partie de l'état de l'entité– Toujours un lien 1:1@Entity
public class Personne { private Adresse _adresse; @Embedded @AttributeOverrides( { @AttributeOverride(name="rue", column=@Column(name="street")), @AttributeOverride(name="ville", column=@Column(name="city")) }) public Adresse getAdresse() { return _adresse; } public void setAdresse(Adresse adresse) { _adresse = adresse; }}
@Embeddablepublic class Adresse { private String _rue; private String _ville; …}
Colonnes de la table PERSONNE
Personne Adresse
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 110
Super classe mappées• Factorise des mapping communs entre
classes• Pas d'annotation pour
contrôler l'héritage– La super-classe est intégrée
dans la définition dela sous classe
@MappedSuperclasspublic class Personne { private String _prénom; private String _nom;
public String getPrenom() {…} @Column(name="NOM") public String getNomDeFamille() {…}}
@Entity@AttributeOverride( name="NomDeFamille", column = @Column(name="NOM2FAMILLE"))public class Employe extends Personne { private String _matricule; public String getMatricule() {…}}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 111
Identité composite 1/2
• L'identité d'une Entité peut être encapsulé dans une classe– Bonne pratique: pourquoi ?
• Deux solutions:
@Entitypublic class Personne { private PersonneID _id;
@EmbeddedId public PersonneID getID() { return _id; }}
@Embeddablepublic class PersonneID { private String _nom; private Date _ddn; … public int hashCode() {…} public boolean equals(Object o) {…}}
L'identificateur map sur une propriété
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 112
Identité composite 2/2
• Chaque propriété de l'identificateur map sur une propriété de l'entité
@Entity@IdClass(ClientID.class)public class Client { private String _nom; private String _prenom; public String getNom() { return _nom; } …}
public class ClientID implements Serializable { private String _nom; private String _prenom; public ClientID() {} public getNom() {…} … public long hashcode() { … } public boolean equals(Object o) { … }}
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 113
Mapper une classe sur plusieurs tables
• L'entité est répartie sur plusieurs tables
• Plus d'une table secondaire:– @SecondaryTables
@Entity@Table(name="PERSONNE")@SecondaryTable( name="PERSONNE_DETAILS", pkJoinColumn=@PrimaryKeyJoinColumn( name="PERSONNE_FK"))public class Personne { private long _id; private String _prénom; private String _nom; private String _couleurYeux; private String _couleurCheuveux; @Column( name="COULEUR_YEUX", table="PERSONNE_DETAILS) public String getCouleurYeux() {…} public String getCouleurCheuveux() {…}}
id PRENOM …
COULEUR_YEUX …PERSONNE_FK
PERSONNE
PERSONNE_DETAILS
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 114
Travaux pratiques
• Ouvrez le projet JP-Lab06-Embedded-Question– Suivez les instructions
JP 1.1 - Template 1.0
Auth
or: T
hiba
ult
Cuvi
llier
– C
reat
ive
Com
mon
s 2.
0
javax.persistence
EJBQLNiveau 2
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 116
EJBQL avancé
Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 117
Opérateurs sur les relations
• IN(<Relation ToMany>)– Jointure entre deux entités– select c from Commande c, IN(c.lignes) l
WHERE l.produit = 'Imprimante'• IS [NOT] EMPTY
– select c from Commande c where c.lignes IS EMPTY
• [NOT] MEMBER OF– Tester si une entité est ou non membre d'une
relation
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 118
Les jointures SQL
• Un JOIN permet de combiner les lignes de plusieurs tables
• Deux types de jointures EJBQL:– [INNER] JOIN– LEFT [OUTER] JOIN
• Prenons un exemple:
id nom1 John Doeuf2 Alain Disoir3 Sophie Fonfec
id nom10 Imprimante11 Souris12 Ecran
client122
Client Commande
13 Clé USBnull
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 119
INNER Join
• Ne retourne pas les valeurs nulles de l'entité jointe– Il n'y a pas Sophie Fonfec dans le résultat !
• select c.nom, p.nom from Client c INNER JOIN c.produits p
• Equivalent:– select c.nom, p.nom from Client JOIN c.produits p– select c.nom, p.nom from Client IN(c.produits) p
p.nomImprimante
SourisEcran
c.nomJohn DoeufAlain DisoirAlain Disoir
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 120
LEFT OUTER JOIN
• Retourne aussi les valeurs null de l'entité jointe• select c.nom, p.nom
from Client c LEFT OUTER JOIN c.produits p
• Equivalent:– select c.nom,p.nom from Client c LEFT JOIN
c.produits p
p.nomImprimante
SourisEcran
c.nomJohn DoeufAlain DisoirAlain Disoir
nullSophie Fonfec
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 121
FETCH
• select p from Produit p JOIN p.client c– Lit les clients et produits en trois requêtes
• select p from Produit p JOIN FETCH p.client c– Lit les clients et produits en une seule requête
ProduitImprimante
SourisEcran
select p from Produit p JOIN p.client cload com.btc.join.Clientload com.btc.join.Client
select p from Produit p JOIN p.client c
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 122
Sous-requêtes EJBQL
• Une requête peut contenir une sous-requête
SELECT c FROM Customer c WHERE ( SELECT COUNT(o) FROM c.orders o ) > 10
SELECT goodCustomer FROM Customer goodCustomer WHERE goodCustomer.balance > ( SELECT avg(c.balance) FROM Customer c )
Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 123
Travaux pratiques
• Ouvrez le projet JP-Lab07-EJBQL2-Question– Suivez les instructions