Formation JPA Java persistence API

123
thor: Thibault Cuvillier – Creative Commons 2.0 JP 1.1 - Template 1.0 Java Persistence API Auteur: Thibault Cuvillier Consultant indépendant [email protected] http://www.btcweb.com

Transcript of Formation JPA Java persistence API

Page 1: 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

Page 2: Formation JPA Java persistence API

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

Page 3: 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

javax.persistence

Introduction

Page 4: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 4

Introduction à javax.persistence

Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé

Page 5: Formation JPA Java persistence API

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

Page 6: Formation JPA Java persistence API

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

Page 7: Formation JPA Java persistence API

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

Page 8: Formation JPA Java persistence API

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

Page 9: Formation JPA Java persistence API

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)

Page 10: Formation JPA Java persistence API

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

Page 11: Formation JPA Java persistence API

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

Page 12: Formation JPA Java persistence API

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é

Page 13: Formation JPA Java persistence API

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

Page 14: Formation JPA Java persistence API

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.

Page 15: Formation JPA Java persistence API

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

EMail

email

0..*

<<Tables>>CLIENT

ID

PRENOM

<<Table>>EMAIL

CLIENT_FK

EMAIL

<<Entity>>Client

idprénomnomtéléphone NOM

TELEPHONE

RUE

VILLE

CODEPOSTAL

Tables

Mapping O/RPOJO

Page 16: Formation JPA Java persistence API

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();

Page 17: Formation JPA Java persistence API

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

Page 18: Formation JPA Java persistence API

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

Page 19: Formation JPA Java persistence API

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

Page 20: Formation JPA Java persistence API

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é)

Page 21: Formation JPA Java persistence API

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

Page 22: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 22

Mapping OR

Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé

Page 23: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 23

Mapping O/R > Mapping simple

• Mapping O/RMapping simpleIdentité simpleCallback

Page 24: Formation JPA Java persistence API

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)

Page 25: Formation JPA Java persistence API

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

Page 26: Formation JPA Java persistence API

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 { … }

Page 27: Formation JPA Java persistence API

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 { … }

Page 28: Formation JPA Java persistence API

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

Page 29: Formation JPA Java persistence API

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é() {…}

Page 30: Formation JPA Java persistence API

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;}

Page 31: Formation JPA Java persistence API

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

Page 32: Formation JPA Java persistence API

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; }

Page 33: Formation JPA Java persistence API

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; }

Page 34: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 34

Mapping O/R > Identité simple

• Mapping O/RMapping simpleIdentité simpleCallback

Page 35: Formation JPA Java persistence API

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.!

Page 36: Formation JPA Java persistence API

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

Page 37: Formation JPA Java persistence API

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

Page 38: Formation JPA Java persistence API

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; }

Page 39: Formation JPA Java persistence API

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; }

Page 40: Formation JPA Java persistence API

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;}

Page 41: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 41

Mapping O/R > Callbacks

• Mapping O/RMapping simpleIdentité simpleCallback

Page 42: Formation JPA Java persistence API

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); } …}

Page 43: Formation JPA Java persistence API

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é

Page 44: Formation JPA Java persistence API

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 !!

Page 45: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 45

Travaux pratiques

• Ouvrez le projet JP-Lab01-Mapping-Question– Suivez les instructions

Page 46: Formation JPA Java persistence API

JP 1.1 - Template 1.0

Auth

or: T

hiba

ult

Cuvi

llier

– C

reat

ive

Com

mon

s 2.

0

javax.persistence

EntityManager

Page 47: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 47

EntityManager

Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé

Page 48: Formation JPA Java persistence API

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)

Page 49: Formation JPA Java persistence API

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();

Page 50: Formation JPA Java persistence API

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

Page 51: Formation JPA Java persistence API

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

Page 52: Formation JPA Java persistence API

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();

Page 53: Formation JPA Java persistence API

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);

Page 54: Formation JPA Java persistence API

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;}

Page 55: Formation JPA Java persistence API

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)

Page 56: Formation JPA Java persistence API

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:

Page 57: Formation JPA Java persistence API

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

Page 58: Formation JPA Java persistence API

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.

!

Page 59: Formation JPA Java persistence API

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 ?

Page 60: Formation JPA Java persistence API

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

Page 61: Formation JPA Java persistence API

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

Page 62: Formation JPA Java persistence API

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; }}

Page 63: Formation JPA Java persistence API

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

Page 64: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 64

Travaux pratiques

• Ouvrez le projet JP-Lab02-EntityManager-Question– Suivez les instructions

Page 65: Formation JPA Java persistence API

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

Page 66: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 66

EJBQL

Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé

Page 67: Formation JPA Java persistence API

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"

Page 68: Formation JPA Java persistence API

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

Page 69: Formation JPA Java persistence API

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

Page 70: Formation JPA Java persistence API

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

Page 71: Formation JPA Java persistence API

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)

Page 72: Formation JPA Java persistence API

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)

Page 73: Formation JPA Java persistence API

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

Page 74: Formation JPA Java persistence API

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

Page 75: Formation JPA Java persistence API

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

Page 76: Formation JPA Java persistence API

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();}

Page 77: Formation JPA Java persistence API

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(); }}

Page 78: Formation JPA Java persistence API

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();}

Page 79: Formation JPA Java persistence API

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();}

Page 80: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 80

Travaux pratiques

• Ouvrez le projet JP-Lab03-EJBQL-Question– Suivez les instructions

Page 81: Formation JPA Java persistence API

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

Page 82: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 82

Mapping avancé

Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé

Page 83: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 83

Mapping des relations

Mapping avancéMapping des relationsMapping de l'héritageAutres mappings

Page 84: Formation JPA Java persistence API

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

Page 85: Formation JPA Java persistence API

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

Page 86: Formation JPA Java persistence API

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

Page 87: Formation JPA Java persistence API

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

Page 88: Formation JPA Java persistence API

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

Page 89: Formation JPA Java persistence API

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);

Page 90: Formation JPA Java persistence API

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() {…}

Page 91: Formation JPA Java persistence API

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

Page 92: Formation JPA Java persistence API

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

Page 93: Formation JPA Java persistence API

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)

Page 94: Formation JPA Java persistence API

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; }}

Page 95: Formation JPA Java persistence API

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; }

Page 96: Formation JPA Java persistence API

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; }}

Page 97: Formation JPA Java persistence API

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; }}

Page 98: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 98

Travaux pratiques

• Ouvrez le projet JP-Lab04-Relation-Question– Suivez les instructions

Page 99: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 99

Mapping de l'héritage

Mapping avancéMapping des relationsMapping de l'héritageAutres mappings

Page 100: Formation JPA Java persistence API

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é

Page 101: Formation JPA Java persistence API

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.

Page 102: Formation JPA Java persistence API

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

Page 103: Formation JPA Java persistence API

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

Page 104: Formation JPA Java persistence API

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;}

Page 105: Formation JPA Java persistence API

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

Page 106: Formation JPA Java persistence API

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;}

Page 107: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 107

Travaux pratiques

• Ouvrez le projet JP-Lab05-Inheritance-Question– Suivez les instructions

Page 108: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 108

Autres mappings

Mapping avancéMapping des relationsMapping de l'héritageAutres mappings

Page 109: Formation JPA Java persistence API

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

Page 110: Formation JPA Java persistence API

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() {…}}

Page 111: Formation JPA Java persistence API

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é

Page 112: Formation JPA Java persistence API

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) { … }}

Page 113: Formation JPA Java persistence API

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

Page 114: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 114

Travaux pratiques

• Ouvrez le projet JP-Lab06-Embedded-Question– Suivez les instructions

Page 115: Formation JPA Java persistence API

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

Page 116: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 116

EJBQL avancé

Introduction à javax.persistanceMappingEntityManagerEJBQLMapping avancéEJBQL avancé

Page 117: Formation JPA Java persistence API

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

Page 118: Formation JPA Java persistence API

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

Page 119: Formation JPA Java persistence API

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

Page 120: Formation JPA Java persistence API

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

Page 121: Formation JPA Java persistence API

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

Page 122: Formation JPA Java persistence API

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 )

Page 123: Formation JPA Java persistence API

Thibault CuvillierCreative Commons 2.0 javax.persistence / Introduction 123

Travaux pratiques

• Ouvrez le projet JP-Lab07-EJBQL2-Question– Suivez les instructions