Support de formation Java Persistence API pour développeurs Java.
Contenu:
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
Enjoy.
2. Contenu de la présentation
•
•
•
•
•
•
Chap
Chap
Chap
Chap
Chap
Chap
1:
2:
3:
4:
5:
6:
Introduction
Mapping objet relationnel – Niveau 1
EntityManager
EJBQL – Niveau 1
Mapping objet relationnel – Niveau 2
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é…)
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
2
5. Accéder à la base de données
Session Http
• Les objets d'une application
1
peuvent être:
*
– Transitoires: ils ne survivent pas
Caddie
1
à l'application
*
– Persistants: ils survivent à l'application
Item
1
• Exemple: dans un système de
*
vente en ligne:
Produit
– La classe Caddie est transitoire,
ne contenant que des informations sur la session
– La classe produit est persistante dans une base de
données.
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
5
6. Les quatre modèles 1/2
transitoire
Le modèle conceptuel
La compréhension de l'utilisateur
Le modèle logique
Modèle objet
Le modèle de présentation
Les données présentées à l'utilisateur
Thibault Cuvillier
Creative Commons 2.0
Le modèle physique
Schéma de la base
javax.persistence / Introduction
6
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
7
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 ?
–…
Suite
• Il y a de nombreuses conceptions possibles…
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
8
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…
PersonneDAO
Personne
prenom
nom
email
Thibault Cuvillier
Creative Commons 2.0
inserer
détruire
modifier
requete(prenom, nom)
javax.persistence / Introduction
9
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
Application
Persistance
POJO
Mapping O/R
• 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
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
10
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
Application
Persistance
POJO
Cache
Mapping O/R
• Mais, comment gérer les transactions ?
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
11
12. Cache transactionnel
• Le cache doit être transactionnel
– Isolation transactionnelle
– Consistance
• Il doit être multi-thread safe
Persistance
POJO
Application
Cache
Mapping O/R
Gestion des transactions
Gestion de la sécurité
• Cette solution est complexe
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
12
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
mapping.xml
Description
du mapping O/R
Persistance
API
Application
Cache
Mapping O/R
Gestion des transactions
Gestion de la sécurité
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
13
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
14
15. Exemple Hibernate 1/2
Client.hbm.xml
<hibernate-mapping>
<<Entity>>
Client
id
prénom
nom
téléphone
POJO
<class name="com.btc.Client" table="CLIENT">
<property name="prénom">
<column name="PRENOM" length="32"/>
</property>
…
</class>
</hibernate-mapping>
Mapping O/R
<<Tables>>
CLIENT
ID
PRENOM
NOM
TELEPHONE
RUE
1
Adresse
rue
ville
codePostal
<<Table>>
EMAIL
0..*
EMail
email
Thibault Cuvillier
Creative Commons 2.0
CLIENT_FK
EMAIL
javax.persistence / Introduction
VILLE
CODEPOSTAL
Tables
15
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("bill@microsoft.com");
client.addEMail("bilou@microsoft.com");
session.save(client);
tx.commit();
session.close();
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
16
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
PersistenceContext
– Fonctionne avec J2SE et J2EE
PersistenceContext
• Contexte de persistance:
– Gère le cache des objets
PersistenceContext
– Transactionnel
– Durée de vie: TRANSACTION ou EXTENDED
– Une application peut utiliser plusieurs contextes
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
17
18. Entités
• Interface unifiée
• Le descripteur de mapping O/R standard
– Peut être généré à partir d'annotations Java5.
@Entity
public 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 !
Mapping par défaut
<<Tables>>
CLIENT
ID
NOM
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
18
19. Cycle de vie des Entités
• Gérée = associée à un contexte de
persistance
Etat
Dans la base
Associé à un contexte
de persistance
Transitoire Non
Non
Existe
Oui
Oui
Détaché
Oui
Non
Détruit
Non
Oui
Non Géré
Transitoire
Détaché
Thibault Cuvillier
Creative Commons 2.0
Géré dans un contexte
persist
cascade
merge
Existe
find
query EJBQL
persist
Détruit
sérialisation
fin de TX
javax.persistence / Introduction
19
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é)
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
20
24. Classe persistante
• Doit être annotée avec @Entity
@Entity(name="Compte"
access=AccessType.PROPERTY)
– name
Nom de l'entité utilisé dans les expressions EJBQL
select c from Compte c where c.solde < 0
– access
Annotation 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
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
24
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
25
26. Mapping 1 classe / 1 table 2/3
• Table: <schéma par
défaut>.Client
• Table: <schéma par
défaut>.CLIENT_TBL
• Table: FORMATION.
CLIENT_TBL
Thibault Cuvillier
Creative Commons 2.0
@Entity
public 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 { … }
javax.persistence / Introduction
26
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
27
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
28
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.
private transient String _pwdDecrypté;
• Attributs non persistant:
Thibault Cuvillier
Creative Commons 2.0
@Transient
public String getPwdDecrypté() {…}
javax.persistence / Introduction
29
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 =
@Basic
true ou false
@Temporal(TemporalType.DATE}
• @Temporal
public Date getDateNaissance() {
– value = TIMESTAMP , return _ddn;
DATE, TIME
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
30
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
31
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
35
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>> Soctété
id
nom
prénom
téléphone
sociétéId
id
nom
Thibault Cuvillier
Creative Commons 2.0
<<Table>> Facture
<<Table>> Client
id
clientId
sociétéId
montantHT
montantTTC
tva
javax.persistence / Introduction
36
37. Identité simple 1/4
• La propriété contenant l'identité: @Id
• Pour une identité technique générée:
• @GeneratedValue
– strategy
NONE: pas de génération - Valeur par défaut
TABLE: utilisation d'une table pour gérer les ID
SEQUENCE: utilisation de séquences (Oracle par ex.)
IDENTITY: génération de la valeur par la base
AUTO: génération par le fournisseur de persistance
– String generator (Si generate != NONE)
Nom du générateur
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
37
38. Identité simple 2/4
• La valeur de l'ID
est contrôlée par
l'application
@Id
public long getId() { return _id; }
@Id
• La valeur de l'ID
est fixée lors
d'un INSERT par
une séquence.
@GeneratedValue(strategy=GenerationType.SEQUENC
E,
generator="CLIENT_ID_SEQ")
@SequenceGenerator(
name="CLIENT_ID_SEQ",
sequenceName="CLIENT_ID",
initialValue=0,
allocationSize=50)
public long getId() { return _id; }
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
38
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
39
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
40
42. Callbacks
• Méthodes déclenchées
pour notifier les
changements d'états
d'une entité
@Entity
public class Login {
private String password;
private String cryptedPassword;
@PrePersist
@PreUpdate
public void preUpdate() {
cryptedPassword = crypt(password);
}
}
Thibault Cuvillier
Creative Commons 2.0
@PostLoad
public void postLoad() {
password = decrypt(cryptedPassword);
}
…
javax.persistence / Introduction
42
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
43
44. Listener d'entité
• Vous pouvez mettre le code des callbacks dans
un listener avec @EntityListener.
Personne.java
@Entity
@EntityListener(com.btc.LogListener)
public class Personne { …}
!
Les listeners sont
hérités !
LogListener.java
public class LogListener {
L'entité est passée en
@PrePersist
! paramètre
public void prePersist(Object o) {
System.out.println("PrePersit(o=" + o+")");
}
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
44
45. Travaux pratiques
• Ouvrez le projet JP-Lab01-Mapping-Question
– Suivez les instructions
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
45
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
48
49. Création d'un EntityManager avec J2SE
Attention, différent pour
• L'EntityManager est créé par une
un serveur J2EE
factory
• La factory contient la description du mapping
EntityManagerFactory factory = Persistence.createEntityManagerFactory(
"em", new Properties());
EntityManager em = factory.createEntityManager();
• Vous pouvez utiliser plusieurs contextes de
persistance dans votre application
– Une factory par contexte de persistence
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
49
50. persistence.xml
• La factory est décrite dans le fichier
Transactions:
META-INF/persistence.xml
•RESOURCE_LOCAL
•JTA
<?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>
Attention avec un serveur J2EE,
</persistence>
utilisation de JNDI et de JTA
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
50
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
51
52. TRANSACTION et EXTENDED 2/2
• Pour créer un EntityManager EXTENDED:
EntityManagerFactory factory = Persistence.createEntityManagerFactory(
"em", new Properties());
EntityManager em = _factory.createEntityManager(
PersistenceContextType.EXTENDED );
…
em.close();
• Il est préférable d'utiliser des caches
transactionnels et de reposer ainsi sur l'isolation
transactionnelle de la base
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
52
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é
persistante
EntityManager em = … on verra plus loin …;
Client client = em.getReference(Client.class, "Bill Gates");
em.remove(client);
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
53
54. Gérer les transactions
EntityManager em = …;
• Pas de transactions
EntityTransaction tx =
imbriquées
em.getTransaction();
• S'il n'y a pas de transaction, tx.begin();
le contexte de persistance, try {
… modifier les données …
la méthode find:
tx.commit();
– en commence une
} catch(Exception e) {
tx.rollback();
– la termine à la fin de la
throw e;
méthode
}
– retourne une entité détachée
• Pour modifier les données dans la base, il
suffit de modifier un objet géré
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
54
55. EntityManager.persist 1/2
• void persist(Object entity)
Etat
Action
Transitoire Insertion dans la base (1)
Géré
Rien sur l'entité(1)
Détaché
IllegalArgumentException
Détruit
L'entité redevient managée (1)
– (1) Cascade sur les entités référencées si
cascade=PERSIST ou ALL
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
55
57. EntityManager.remove
• void remove(Object entity)
Etat
Action
Transitoire
Rien sur l'entité, mais cascade (1)
Géré
Destruction de l'entité et cascade (1)
Détaché
IllegalArgumentException
Détruit
Rien
– (1) Cascade sur les entités référencées si
cascade=REMOVE ou ALL
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
57
58. EntityManager.merge
• <T> T merge(T entity)
– Retourne une nouvel
entité géré
!
Attention, avec Hibernate,
provoque une lecture de l'objet
pour comparer son état.
Etat
Transitoire
Géré
Action
Création de l'entité (1)
Rien sur l'entité (1)
Détaché
Copie de l'état dans une entité gérée avec la
même identité (1)
IllegalArgumentException
Détruit
– (1) Cascade sur les entités référencées si
cascade=MERGE ou ALL javax.persistence / Introduction
Thibault Cuvillier
Creative Commons 2.0
58
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 transactionnelles
public Client fetchClient(long idclient) {
EntityManager em = …;
return em.find(Client.class, idclient);
}
Ne pas utiliser getReference:
pourquoi ?
public void saveClient(Client client) {
EntityManager em = …;
em.merge(client);
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
59
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é
EJB Session
EntityManager
Navigateur
Web
GET EditClient.jsp
Client c = fetchClient("Bill Gates")
find
SELECT
POST EditClient.jsp
saveClient(c)
merge
UPDATE
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
Base
60
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
61
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,
Timestamp
public Person {
private long _version;
@Version
public long getVersion() {
return _version;
}
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
62
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
63
64. Travaux pratiques
• Ouvrez le projet JP-Lab02-EntityManagerQuestion
– Suivez les instructions
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
64
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
67
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
68
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és
select new com.btc.EmployeInfo(e.id, e.status, e.salaire) from Employe e
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
69
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
70
72. Opérateurs de la clause WHERE 3
• EXISTS
– Vrai si la sous-requête retourne au moins un objet
SELECT DISTINCT emp FROM Employee emp WHERE
EXISTS (
SELECT spouseEmp FROM Employee spouseEmp
WHERE spouseEmp = emp.spouse)
• ALL, ANY (ou SOME)
– ALL: Vrai si toutes les valeurs remplissent la condition
– ANY: Vrai si une valeur au moins remplie la condition
SELECT emp FROM Employee emp WHERE emp.salary > ALL (
SELECT m.salary FROM Manager m
WHERE m.department = emp.department)
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
72
73. GROUP BY
• GROUP BY permet de regrouper
les valeurs retournées par
la requête
• Requête sans clause GROUP BY:
Entreprise
SUN
Montant
5500
IBM
SUN
4500
7100
Entreprise
Montant
SUN
17100
IBM
17100
SUN
17100
Entreprise
Montant
IBM
4500
SUN
12600
select v.entreprise, SUM(v.montant)
from Vente v
• Requête avec la clause GROUP BY:
select v.entreprise, SUM(v.montant)
from Vente v group by c.entreprise
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
73
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
Thibault Cuvillier
Creative Commons 2.0
Entreprise
Montant
SUN
12600
javax.persistence / Introduction
74
75. DELETE et UPDATE
• Permet de déclencher des delete et update de
masse dans un batch.
• DELETE:
• UPDATE:
delete from Client c where c.status = 0
update Employe c set c.salary = 1500 where c.salary < 1500
• Le contexte de persistance n'est pas mis à jour
• Utiliser:
– Dans une transaction séparée
– Au début d'une nouvelle transaction
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
75
76. Exécuter une requête simples
• Les requêtes simples
public List findClients(EntityManager em) {
Query query = em.createQuery ("select c from Client c");
return query.getResultList ();
}
• Avec des paramètres
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
76
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
77
78. Utiliser le SQL natif
• Vous pouvez utiliser des requêtes SQL
public List getClients() {
Query query = _em.createNativeQuery ("select * from client", Client.class);
return query.getResultList();
}
• Vous pouvez utiliser @NamedNativeQuery
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
78
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
79
80. Travaux pratiques
• Ouvrez le projet JP-Lab03-EJBQL-Question
– Suivez les instructions
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
80
83. Mapping des relations
Mapping avancé
Mapping des relations
Mapping de l'héritage
Autres mappings
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
83
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 …
remove
– Que sur les relations
OneToOne ou OneToMany
Commande
remove
Ligne1
Thibault Cuvillier
Creative Commons 2.0
remove
Ligne2
javax.persistence / Introduction
remove
Ligne3
84
85. Relation 1-1
Map sur la table PERSONNE
Propriétaire de la relation
@Entity
public class Personne {
private long _id;
private Login _login;
@OneToOne
public Login getLogin() {
return _login;
}
public void setLogin(Login login) {
_login = login;
}
Map sur la
colonne ID
Map sur la table LOGIN
@Entity
public 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;
}
}
PERSONNE contient une FK sur LOGIN
colonne = <Propriété>_<column PK> = LOGIN_ID
Thibault Cuvillier
Creative Commons 2.0
Optionnel si la
relation est
unidirectionnelle
}
javax.persistence / Introduction
85
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 = EAGER
Accès aux entités en mode LAZY ou EAGER
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
86
87. Fetch des entités
• EAGER:
– Les objets liés sont chargés en une seule requête SQL
1 find(Personne.class, id)
2 getLogin()
EntityManager
Personne
Login
• LAZY:
– Chargement de l'identité
– Chargement de l'état lors du premier accès
1 find(Personne.class, id)
2 getLogin()
Thibault Cuvillier
Creative Commons 2.0
EntityManager
Personne
javax.persistence / Introduction
Login
87
88. Relation 1-n
Map sur la table LOGIN
Propriétaire de la relation
@Entity
public class Login {
private long _id;
private Role _role;
Map sur la
colonne ID
Map sur la table ROLE
@Entity
public class Role {
private long _id;
private List<Login> _logins;
@ManyToOne
public Role getRole() {
return _role;
}
public void setRole(Role r) {
_role = r;
}
Optionnel si la
relation est
unidirectionnelle
@OneToMany(mappedBy="role")
public List<Login> getLogins() {
return _logins;
}
public void setLogins(List<logins> l) {
_logins = l;
}
}
}
LOGIN contient une FK sur ROLE
colonne = <Propriété>_<column PK> = ROLE_ID
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
88
89. Intégrité des relations
• C'est au développeur d'assurer l'intégrité des
relations
– Positionner la relation inverse Login login = new Login();
Person person = new Person();
– Lors du chargement, le lien
inverse est positionné
login.setPerson(person);
automatiquement
person.setLogin(login);
• Une relation est mise à jour dans la base à partir
de son propriétaire
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
89
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:
@OneToMany(mappedBy="role")
List<Personne> getPersonnes() {…}
• Avec les collections non génériques:
@OneToMany(targetEntity=Personne.class, mappedBy="role")
List getPersonnes() {…}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
90
91. Relation n-m
Map sur la table ROLE
Propriétaire de la relation
@Entity
public class Role {
private long _id;
private List<Authorization> _authorizations;
@ManyToMany
public List<Authorization> getAuthorizations() {
return _authorizations;
}
public void setAuthorization(List<Authorization> a) {
_authorizations = a;
}
}
Map sur la table
AUTHORIZATION
Map sur la
colonne ID
@Entity
public class Authorization {
private long _id;
private List<Role> _roles;
Optionnel si la
relation est
unidirectionnelle
@ManyToMany(mappedBy="authorizations")
public List<Role> getRoles() {
return _roles;
}
public void setRoles(List<Role> r) {
_roles = r;
}
Table d'association: ROLE_AUTORIZATIONS
PK: ROLE_ID
PK: AUTHORIZATIONS_ID
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
91
92. Mapping d'une clé étrangère 1/2
Jointure
composite
Jointure
simple
@Entity
public class Login {
private long _id;
private Role _role;
@ManyToOne
@JoinColumn(
name="ROLE_FK")
public Role getRole() {
return _role;
}
}
Thibault Cuvillier
Creative Commons 2.0
@Entity
public 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;
}
}
92
javax.persistence / Introduction
93. Mapping d'une clé étrangère 2/2
• @JoinColumn
– (O) String name
Nom de la colonne contenant la clef étrangère.
Par défaut: <Propriété du référant>_<PK du référé>
– (O) String referencedColumnName
Clef 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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
93
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
94
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
95
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
@Entity
public 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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
96
97. BLOB et CLOB
• Permet de préciser le type d'une colonne
contenant un Large OBject
@Entity
– Propriété String
public class Role {
CLOB: données texte
private JPEGImage _image;
– Autre type de donnée
@Lob
BLOB: données binaires
• fetch: EAGER ou
@Basic(fetch=FetchType.LAZY)
public JPEGImage getPhoto() {
LAZY
return _image;
}
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
97
98. Travaux pratiques
• Ouvrez le projet JP-Lab04-Relation-Question
– Suivez les instructions
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
98
99. Mapping de l'héritage
Mapping avancé
Mapping des relations
Mapping de l'héritage
Autres mappings
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
99
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
100
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
id
couleur
0..n
1
Berline
barresDeToit
Attention, toutes les
propriétés doivent être
nullable.
Personne
Cabriolet
toit=capote, hardtop
VOITURE
disc
Thibault Cuvillier
Creative Commons 2.0
propriétaire
id
couleur
proprietaire
javax.persistence / Introduction
barresDeToit
toit
101
102. Une table par hiérarchie: exemple
@Entity
@Inheritance(
strategy=SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType=STRING
)
public abstract class Voiture {
@Id long _id;
private Personne _propriétaire;
STRING, CHAR,
private String _couleur;
INTEGER
…
}
• Chaque sous
classe doit
utiliser une
valeur différente
du discriminateur
@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;
}
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
102
103. Une table par classe concrète
• Consomme peu de place
disque
• Requêtes polymorphes
coûteuses
Voiture
id
couleur
propriétaire
0..n
1
Berline
Personne
Cabriolet
barresDeToit
toit=capote, hardtop
Le support de ce
mapping est optionnel
CABRIOLET
BERLINE
id
couleur
proprietaire
Thibault Cuvillier
Creative Commons 2.0
barresDeToit
id
couleur
javax.persistence / Introduction
proprietaire
toit
103
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;
…
}
@Entity
public class Berline extends
Voiture {
private boolean barresDeToit;
@Entity
public class Cabriolet extends Voiture {
public enum Toit {HARDTOP, CAPOTE};
private Toit _toit;
}
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
104
105. Une table par classe
• Proche du modèle objet
• Performance des
requêtes
Voiture
id
couleur
propriétaire
0..n
Personne
1
Berline
Cabriolet
barresDeToit
toit=capote, hardtop
VOITURE
id
couleur
proprietaire
BERLINE
id
Thibault Cuvillier
Creative Commons 2.0
barresDeToit
javax.persistence / Introduction
CABRIOLET
id
toit
105
106. Une table par classe: exemple
@Entity
@Inheritance(strategy=JOINED
)
public abstract class Voiture {
@Id long _id;
private Personne _propriétaire;
private String
_couleur;
…
}
@Entity
public class Berline extends
Voiture {
private boolean barresDeToit;
}
• Les sous classes
contiennent une FK sur
la classe de base
• Peut être renommée
avec
@PrimaryKeyJoinColum
n
@Entity
public class Cabriolet extends Voiture {
public enum Toit {HARDTOP,
CAPOTE};
private Toit _toit;
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
106
107. Travaux pratiques
• Ouvrez le projet JP-Lab05-Inheritance-Question
– Suivez les instructions
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
107
108. Autres mappings
Mapping avancé
Mapping des relations
Mapping de l'héritage
Autres mappings
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
108
109. Les classes embedded
• Classe Java contenant une partie de l'état de
l'entité
@Embeddable
public class Adresse {
– Toujours un lien 1:1
@Entity
Personne
public class Personne {
private Adresse _adresse;
Adresse
Colonnes de la table
PERSONNE
private String _rue;
private String _ville;
…
}
@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; }
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
109
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 @MappedSuperclass
public class Personne {
dans la définition de
private String _prénom;
private String _nom;
la sous classe
@Entity
@AttributeOverride(
name="NomDeFamille",
column = @Column(name="NOM2FAMILLE"))
public class Employe extends Personne {
private String _matricule;
public String getMatricule() {…}
}
Thibault Cuvillier
Creative Commons 2.0
public String getPrenom() {…}
@Column(name="NOM")
public String getNomDeFamille() {…}
}
javax.persistence / Introduction
110
111. Identité composite 1/2
• L'identité d'une Entité peut être encapsulé dans
une classe
– Bonne pratique: pourquoi ?
• Deux solutions:
@Embeddable
public class PersonneID {
private String _nom;
@Entity
public class Personne {
L'identificateur mapprivate Date _ddn;
sur une propriété …
private PersonneID _id;
public int hashCode() {…}
public boolean equals(Object o) {…}
@EmbeddedId
}
public PersonneID getID() { return _id; }
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
111
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 class ClientID
implements Serializable {
private String _nom;
private String _prenom;
public ClientID() {}
public getNom() {…}
…
public long hashcode() { … }
public boolean equals(Object o) {
…
}
public String getNom() {
return _nom;
}
…
}
}
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
112
113. Mapper une classe sur plusieurs tables
@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() {…}
}
Thibault Cuvillier
Creative Commons 2.0
• L'entité est répartie sur
plusieurs tables
• Plus d'une table
secondaire:
– @SecondaryTables
PERSONNE
id
PRENOM
…
PERSONNE_DETAILS
PERSONNE_FK
COULEUR_YEUX
javax.persistence / Introduction
…
113
114. Travaux pratiques
• Ouvrez le projet JP-Lab06-Embedded-Question
– Suivez les instructions
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
114
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
117
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
1
2
3
Client
nom
John Doeuf
Alain Disoir
Sophie Fonfec
Thibault Cuvillier
Creative Commons 2.0
id
10
11
12
13
Commande
client
nom
1
Imprimante
2
Souris
2
Ecran
null
Clé USB
javax.persistence / Introduction
118
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
c.nom
p.nom
John Doeuf
Alain Disoir
Alain Disoir
Imprimante
Souris
Ecran
• Equivalent:
– select c.nom, p.nom from Client JOIN c.produits p
– select c.nom, p.nom from Client IN(c.produits) p
javax.persistence / Introduction
Thibault Cuvillier
Creative Commons 2.0
119
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
c.nom
John Doeuf
Alain Disoir
Alain Disoir
Sophie Fonfec
p.nom
Imprimante
Souris
Ecran
null
• Equivalent:
– select c.nom,p.nom from Client c LEFT JOIN c.produits
p
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
120
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 p.client c
load com.btc.join.Client
load com.btc.join.Client
Produit
Imprimante
Souris
Ecran
• select p from Produit p JOIN FETCH p.client c
– Lit les clients et produits en une seule requête
select p from Produit p JOIN p.client c
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
121
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 Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
122
123. Travaux pratiques
• Ouvrez le projet JP-Lab07-EJBQL2-Question
– Suivez les instructions
Thibault Cuvillier
Creative Commons 2.0
javax.persistence / Introduction
123