JPA avec EclipseLink
Achref El Mouelhi
Docteur de l’université d’Aix-Marseille
Chercheur en programmation par contrainte (IA)
Ingénieur en génie logiciel
[Link]@[Link]
H & H: Research and Training 1 / 94
Plan
1 Introduction
2 Créer une connexion
3 Créer un JPA Project
4 Entity
Création d’une entité
Création de tables associées aux entités
Création des entités à partir d’une BD existante
H & H: Research and Training 2 / 94
Plan
5 EntityManager
Insertion
Mise à jour
Suppression
Consultation
6 JPQL : Java Persistence Query Language
7 Relation entre entités
OneToOne
ManyToOne
OneToMany
ManyToMany
Inheritance
H & H: Research and Training 3 / 94
Plan
8 Les classes incorporables
9 Les méthodes callback
10 Utilisation de l’API JPA dans un projet JEE
11 Utilisation de l’API JPA dans un projet Maven
H & H: Research and Training 4 / 94
Introduction
Object-Relational Mapping (lien objet-relationnel)
Définition
est une couche d’abstraction à la base de données
est une classe qui permet à l’utilisateur d’utiliser les tables d’une
base de données comme des objets
consiste à associer :
une ou plusieurs classes à chaque table
un attribut de classe à chaque colonne de la table
a comme objectif de ne plus écrire de requête SQL
H & H: Research and Training 5 / 94
Introduction
Object-Relational Mapping (lien objet-relationnel)
Définition
est une couche d’abstraction à la base de données
est une classe qui permet à l’utilisateur d’utiliser les tables d’une
base de données comme des objets
consiste à associer :
une ou plusieurs classes à chaque table
un attribut de classe à chaque colonne de la table
a comme objectif de ne plus écrire de requête SQL
Plusieurs ORM proposés pour chaque Langage de POO.
H & H: Research and Training 5 / 94
Introduction
Object-Relational Mapping
Pour Java
EclipseLink
Hibernate
Java Data Objects (JDO)
...
H & H: Research and Training 6 / 94
Introduction
Object-Relational Mapping
Pour Java
EclipseLink
Hibernate
Java Data Objects (JDO)
...
Quel choix pour PHP ? !
Doctrine
pdoMap
RedBean
...
H & H: Research and Training 6 / 94
Introduction
JPA
EclipseLink ?
est un framework open source de mapping objet-relation
est dérivé du projet TopLink d’Oracle (un framework d’ORM open
source acheté par Oracle en 2002)
supporte l’API de persistence de données JPA
H & H: Research and Training 7 / 94
Introduction
JPA
JPA : Java Persistence API
est une interface standardisée par Sun, qui permet l’organisation
des données
a été proposé par JSR (Java Specification Requests)
s’appuie sur l’utilisation des annotations pour définir le lien entre
Entity (classe) et table (en base de données relationnelle) et sur
le gestionnaire EntityManager pour gérer les données
(insertion, modification...)
H & H: Research and Training 8 / 94
Introduction
JPA
Étapes
Création d’une connexion
Création d’un JPA Project
Création des entités et bien utiliser les annotations
Établissement de liens entre entités
Création des tables, à partir des entités, si elles n’existent pas
Manipulation des entités (ajout, suppression, modification,
consultation) avec EntityManager
H & H: Research and Training 9 / 94
Créer une connexion
Créer une connexion
Avant de créer une connexion
créer une base de données appelée jpa
H & H: Research and Training 10 / 94
Créer une connexion
Créer une connexion
Avant de créer une connexion
créer une base de données appelée jpa
Création d’une connexion à la base de données (jpa)
Aller dans menu File ensuite New et enfin choisir Other
Chercher Connection Profile
Sélectionner le SGBD (dans notre cas MySQL)
Attribuer un nom à cette connexion dans Name
Cliquer sur New Driver Definition devant la liste déroulante de Drivers
Définir le driver en choisissant le dernier MySQL JDBC DRIVER, en précisant son
emplacement dans la rubrique JAR List, en supprimant celui qui existait et en modifiant
les données dans la rubrique Properties
Vérifier ensuite l’URL, User name, Password et DataBase Name (jpa) et Valider
H & H: Research and Training 10 / 94
Créer une connexion
Création d’une connexion
Tester la connexion
Aller dans l’onglet Data Source Explorer
Faire un clic droit et ensuite choisir Connect
H & H: Research and Training 11 / 94
Créer un JPA Project
JPA
Création d’un projet JPA
Aller dans menu File > New > JPA Project
Saisir FirstJpaProject comme nom du projet
Choisir jre1.8 dans Target runtime et cliquer deux fois sur Next
Dans Platform, choisir la dernière version d’EclipseLink (2.5.2)
Dans Type de JPA Implementation, choisir User Library
Ensuite cocher la case EclipseLink et cliquer sur Download
Library... à droite (pour démarrer le téléchargement)
Dans Connection, choisir la connexion définie précédemment
Cocher la case Add driver library to build path et valider
H & H: Research and Training 12 / 94
Créer un JPA Project
JPA
Le fichier [Link]
est situé dans le répertoire META-INF de src
contient les données sur le mapping entre nos entités/ et nos
tables dans la base de données
H & H: Research and Training 13 / 94
Entity
Une entité (Entity)
Définition
correspond à une table d’une base de données relationnelle
est un objet (Javabean) contenant quelques informations
indispensables (annotations) pour le mapping (faire le lien) avec la
base de données
H & H: Research and Training 14 / 94
Entity Création d’une entité
Une entité
Pour une meilleure organisation
Créer un package [Link] sous src
Placer toutes les entités dans ce package
H & H: Research and Training 15 / 94
Entity Création d’une entité
Une entité
Pour une meilleure organisation
Créer un package [Link] sous src
Placer toutes les entités dans ce package
Création
Faire un clic droit sur [Link], aller dans new et choisir JPA
Entity
Saisir un nom dans Class name:, ensuite cliquer sur Next
Avec le bouton Add..., ajouter les différents attributs ainsi que leur type
Cocher la case correspondant à la clé primaire puis cliquer sur Finish
Vérifier dans [Link] que la ligne
<class>[Link]</class> a bien été ajoutée.
H & H: Research and Training 15 / 94
Entity Création d’une entité
Une entité
public Personne() {
package [Link]; super();
import [Link]; }
import [Link];
import [Link].*; public int getNum() {
return [Link];
/** }
* Entity implementation class for public void setNum(int num) {
Entity: Personne [Link] = num;
* }
*/ public String getNom() {
@Entity return [Link];
public class Personne implements }
Serializable { public void setNom(String nom) {
[Link] = nom;
@Id }
@GeneratedValue (strategy= public String getPrenom() {
[Link]) return [Link];
private int num; }
private String nom; public void setPrenom(String
private String prenom; prenom) {
[Link] = prenom;
private static final long }
serialVersionUID = 1L; }
H & H: Research and Training 16 / 94
Entity Création d’une entité
Une entité
Autres annotations
Annotation désignation
@Entity permet de qualifier la classe comme entité
@Id indique l’attribut qui correspond à la clé primaire de la table
@Table décrit la table désignée par l’entité
@Column définit les propriétés d’une colonne
@IdClass indique que l’entité annotée contient une clé composée
les champs constituant la clé seront annoté par @Id
@GeneratedValue s’applique sur les attributs annotés par @Id
permet la génération automatique de la clé primaire
H & H: Research and Training 17 / 94
Entity Création d’une entité
Une entité
Autres annotations
Annotation désignation
@Entity permet de qualifier la classe comme entité
@Id indique l’attribut qui correspond à la clé primaire de la table
@Table décrit la table désignée par l’entité
@Column définit les propriétés d’une colonne
@IdClass indique que l’entité annotée contient une clé composée
les champs constituant la clé seront annoté par @Id
@GeneratedValue s’applique sur les attributs annotés par @Id
permet la génération automatique de la clé primaire
// la classe Personne // la classe PersonnePK
@IdClass([Link]) public class PersonnePK {
@Entity @Id
public class Personne implements private String nom;
Serializable { @Id
@Id private String prenom;
private String nom; // ensuite getters, setters,
@Id constructeur sans parametres et
private String prenom; constructeur avec deux
// ensuite getters, setters et parametres nom et prenoms
constructeur
H & H: Research and Training 17 / 94
Entity Création d’une entité
Une entité
Attributs de l’annotation @Column
Attribut désignation
name permet de définir le nom de la colonne
s’il est différent de celui de l’attribut
length permet de fixer la longueur d’une chaı̂ne de caractères
unique indique que la valeur d’un champ est unique
nullable précise si un champ est null (ou non)
... ...
H & H: Research and Training 18 / 94
Entity Création d’une entité
Une entité
Attributs de l’annotation @Table
Attribut désignation
name permet de définir le nom de la table
s’il est différent de celui de l’entité
uniqueConstraints permet de définir des contraintes d’unicité sur
un ensemble de colonnes
@Table(
name="personne",
uniqueConstraints={
@UniqueConstraint(name="nom_prenom", columnNames
={"nom", "prenom"})
}
)
H & H: Research and Training 19 / 94
Entity Création d’une entité
Une entité
L’annotation @Transient
L’attribut annoté par @Transient n’aura pas de colonne associée
dans la table correspondante à l’entité en base de données.
H & H: Research and Training 20 / 94
Entity Création de tables associées aux entités
Création de tables associées aux entités
Étapes
Un clic droit sur le projet
Aller dans JPA Tools
Choisir Generate Tables from Entities
H & H: Research and Training 21 / 94
Entity Création des entités à partir d’une BD existante
Création des entités à partir d’une BD existante
Étapes
Un clic droit sur le projet
Aller dans JPA Tools
Choisir Generate Entities from Tables
Sélectionner la connexion ensuite les tables à importer
Choisir le package dans lequel les entités seront importées
Valider
H & H: Research and Training 22 / 94
Entity Création des entités à partir d’une BD existante
Création des entités à partir d’une BD existante
Si les entités ne contiennent pas les colonnes
Supprimer les entités générées
Utiliser le Data Source Name pour se déconnecter et se
reconnecter
(vous pouvez même dans certains cas étendre l’arborescence de
chaque table dans le Data Source Name)
Régénérer les entités
H & H: Research and Training 23 / 94
EntityManager
EntityManager
Pour persister les données, il faut
ajouter les données concernant la connexion à la base de données dans
le fichier [Link]
instancier et utiliser un gestionnaire d’entités pour manipuler les
données
H & H: Research and Training 24 / 94
EntityManager
EntityManager
Pour persister les données, il faut
ajouter les données concernant la connexion à la base de données dans
le fichier [Link]
instancier et utiliser un gestionnaire d’entités pour manipuler les
données
Gestionnaire d’entités (EntityManager) ?
est une classe Java
assure l’interaction entre la base de données et les entités
permet via les entités, définies dans la section persistence-unit du
fichier [Link], de lire ou écrire des données dans la base
de données
H & H: Research and Training 24 / 94
EntityManager
EntityManager
Comment obtenir une instance d’EntityManager
il faut utiliser une fabrique de type EntityManagerFactory
Cette dernière a une méthode createEntityManager() qui
permet d’obtenir un EntityManager
Pour obtenir une instance de la fabrique, il faut utiliser la méthode
statique createEntityManagerFactory() de la classe
Persistence qui prend comme paramètre le nom de l’unité de
persistence à utiliser (défini dans le fichier [Link])
H & H: Research and Training 25 / 94
EntityManager
EntityManager
Le fichier [Link]
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
persistence [Link]
persistence_2_1.xsd">
<persistence-unit name="FirstJpaProject">
<class>[Link]</class>
</persistence-unit>
</persistence>
Obtenir l’EntityManager
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
H & H: Research and Training 26 / 94
EntityManager
EntityManager
Quelques méthodes de l’EntityManager
persist(obj) : pour stocker obj dans la base de données
find(NomClasse, id) : pour chercher un élément de type
NomClasse ayant l’identifiant id
flush() : pour sauvegarder les modifications dans la base de
données
remove(obj) : pour supprimer obj de la base de données
...
H & H: Research and Training 27 / 94
EntityManager Insertion
EntityManager
Commençons par ajouter les informations sur la connexion dans [Link]
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<persistence-unit name="FirstJpaProject">
<class>[Link]</class>
<properties>
<property name="[Link]" value="[Link]" />
<property name="[Link]" value="jdbc:mysql://localhost:3306/jpa" />
<property name="[Link]" value="root" />
<property name="[Link]" value="" />
<property name="[Link]-database" value="MySQL5" />
<property name="[Link]-generation" value="drop-and-create-tables" />
<property name="[Link]-mode" value="both" />
<property name="[Link]" value="FINE" />
</properties>
</persistence-unit>
</persistence>
ddl : data definition language (ou langage de définition de données (LDD)).
H & H: Research and Training 28 / 94
EntityManager Insertion
EntityManager
Valeurs possibles pour ddl-generation
drop-and-create-tables : EclipseLink essayera de
supprimer toutes les tables, puis de les recréer toutes. (très utile
pour la phase de développement pendant les tests ou lorsque les
données existantes doivent être effacées.
create-or-extend-tables : EclipseLink essayera de créer
des tables. Si la table existe, il ajoutera les colonnes manquantes.
create-tables : EclipseLink essayera d’exécuter CREATE
TABLE pour chaque table. Si la table existe déjà, une exception
est levée et la table n’est pas créée. la table existante sera utilisée.
EclipseLink poursuivra ensuite avec la prochaine instruction.
none : Aucun LDD généré (aucune CREATE TABLE). Aucun
schéma généré.
H & H: Research and Training 29 / 94
EntityManager Insertion
EntityManager
Valeurs possibles pour [Link]-mode
both : Le LDD sera généré et écrit à la fois dans la base de
données et dans un fichier.
database : (Valeur par défaut) Le LDD sera généré et écrit
uniquement dans la base de données.
sql-script : DDL sera généré et écrit uniquement dans un
fichier.
Ce mode dépend évidemment de la configuration précédente (la
valeur choisie pour ddl-generation).
H & H: Research and Training 30 / 94
EntityManager Insertion
L’insertion
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
// instanciation de l’entité
Personne p = new Personne();
[Link]("John");
[Link]("Wick");
EntityTransaction transaction = [Link]();
[Link](); // début transaction
[Link](p); // persister dans la base de données
[Link](); // valider transaction
// fermer l’EntityManager et la factorie
[Link]();
[Link]();
H & H: Research and Training 31 / 94
EntityManager Insertion
L’insertion
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
// instanciation de l’entité
Personne p = new Personne();
[Link]("John");
[Link]("Wick");
EntityTransaction transaction = [Link]();
[Link](); // début transaction
[Link](p); // persister dans la base de données
[Link](); // valider transaction
// fermer l’EntityManager et la factorie
[Link]();
[Link]();
[Link]() pour annuler la transaction
H & H: Research and Training 31 / 94
EntityManager Mise à jour
La mise à jour
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
// chercher l’élément a modifier
Personne p = [Link]([Link], 10); // on indique la
classe et la valeur de la clé primaire
EntityTransaction transaction = [Link]();
[Link]();
if (p == null) {
[Link]("Personne non trouvée");
}
else {
[Link]("Bob"); // faire une modification
[Link](); // enregistrer la modification
}
// valider la transaction
[Link]();
[Link]();
[Link]();
H & H: Research and Training 32 / 94
EntityManager Suppression
La suppression
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
// chercher l’élément a supprimer
Personne p = [Link]([Link], 10);
EntityTransaction transaction = [Link]();
[Link]();
if (p == null) {
[Link]("Personne non trouvée");
}
else {
// supprimer l’élément
[Link](p);
}
// valider la transaction
[Link]();
[Link]();
[Link]();
H & H: Research and Training 33 / 94
EntityManager Consultation
La recherche
Fonctions de recherche
find() : cherche et retourne un élément selon la valeur de la clé
primaire. Retourne null si la valeur n’existe pas
getReference() : fonctionne comme find(). Mais elle
déclenche une exception si la valeur n’existe pas
H & H: Research and Training 34 / 94
EntityManager Consultation
La recherche
Fonctions de recherche
find() : cherche et retourne un élément selon la valeur de la clé
primaire. Retourne null si la valeur n’existe pas
getReference() : fonctionne comme find(). Mais elle
déclenche une exception si la valeur n’existe pas
On peut aussi définir nos fonctions de recherche en utilisant des
requêtes SQL
H & H: Research and Training 34 / 94
EntityManager Consultation
La consultation
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
// definir la requete
String str = "select * from Personne";
// executer la requete et preciser l’entite concernee
Query query = [Link](str, [Link]
.[Link]);
// recuperer le resultat
List <Personne> personnes = (List <Personne> ) query.
getResultList();
for (Personne p : personnes) {
[Link]("nom = "+ [Link]());
}
[Link]();
[Link]();
H & H: Research and Training 35 / 94
EntityManager Consultation
La recherche
Création de requêtes
createNativeQuery() : permet d’exécuter une requête SQL
createNamedQuery() : permet d’exécuter une requête JPQL
définie par des annotations
createQuery() : permet d’exécuter une requête JPQL
H & H: Research and Training 36 / 94
EntityManager Consultation
La recherche
Création de requêtes
createNativeQuery() : permet d’exécuter une requête SQL
createNamedQuery() : permet d’exécuter une requête JPQL
définie par des annotations
createQuery() : permet d’exécuter une requête JPQL
Récupération du résultat
getResultList() : permet de récupérer le résultat sous forme
d’une liste
getSingleResult() : permet de récupérer un seul élément de
la sélection
getFirstResult() : permet de récupérer le premier élément
de la sélection
H & H: Research and Training 36 / 94
EntityManager Consultation
La consultation
Les requêtes natives : exemple avec getSingleResult() en
utilisant les requêtes paramétrées
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
Query query = [Link]("select * from
Personne where num = ?", [Link].
[Link]);
[Link](1, 5);
Personne p = (Personne) [Link]();
[Link]("nom = "+ [Link]());
[Link]();
[Link]();
H & H: Research and Training 37 / 94
EntityManager Consultation
La consultation
Les requêtes nommées : exemple (on commence tout d’abord par
définir la requête dans l’entité)
/**
* Entity implementation class for Entity: Personne
*
*/
@Entity
@NamedQuery(
name="findByNomPrenom",
query="SELECT p FROM Personne p WHERE [Link] = :
nom and [Link] = :prenom"
)
public class Personne implements Serializable {
...
H & H: Research and Training 38 / 94
EntityManager Consultation
La consultation
Les requêtes nommées : exemple (ensuite nous l’utiliserons)
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
Query query = [Link]("findByNomPrenom")
;
[Link]("nom", "Wick");
[Link]("prenom", "John");
List <Personne> personnes = (List <Personne> ) query
.getResultList();
for (Personne p : personnes) {
[Link]("nom = "+ [Link]());
}
[Link]();
[Link]();
H & H: Research and Training 39 / 94
EntityManager Consultation
La consultation
Et si on veut définir plusieurs requêtes nommées
@Entity
@NamedQueries({
@NamedQuery(
name="findByNomPrenom",
query="SELECT p FROM Personne p WHERE [Link] = :
nom and [Link] = :prenom"
),
@NamedQuery(
name="findByPrenom",
query="SELECT p FROM Personne p WHERE [Link] =
:prenom"
),
})
public class Personne implements Serializable {
...
H & H: Research and Training 40 / 94
EntityManager Consultation
EntityManager
Les méthodes utilisées de l’EntityManager
persist(entity) : permet de persister une entité. Un commit
engendrera l’enregistrement de cette entité dans la base de
données.
remove(entity) : permet de rendre une entité non persistante.
Un commit engendrera la suppression de cette entité de la base
de données.
flush() : permet de persister les modifications. Un commit
engendrera l’enregistrement de ces modifications dans la base de
données.
H & H: Research and Training 41 / 94
EntityManager Consultation
EntityManager
Les méthodes utilisées de l’EntityManager
persist(entity) : permet de persister une entité. Un commit
engendrera l’enregistrement de cette entité dans la base de
données.
remove(entity) : permet de rendre une entité non persistante.
Un commit engendrera la suppression de cette entité de la base
de données.
flush() : permet de persister les modifications. Un commit
engendrera l’enregistrement de ces modifications dans la base de
données.
Attention
La méthode flush() ne prend pas de paramètre
H & H: Research and Training 41 / 94
EntityManager Consultation
EntityManager
Autres méthodes de l’EntityManager
refresh(entity) : permet de synchroniser l’état de l’entité
passée en paramètre (entity) avec son état en base de
données.
detach(entity) : permet de détacher l’entité passée en
paramètre (entity) de l’EntityManager qui la gère.
merge(entity) : permet d’attacher l’entité passée en paramètre
(entity), gérée par un autre EntityManager, à
l’EntityManager courant.
H & H: Research and Training 42 / 94
EntityManager Consultation
EntityManager
Exemple avec utilisation de refresh()
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
//on suppose que John Wick avec un num 10 existe
dans la BD
Personne p = [Link]([Link], 10);
[Link]("Travolta");
[Link](p);
[Link]("le nom est " + [Link]());
// imprime Wick
[Link]();
[Link]();
// si on supprime [Link](p); Travolta sera
affiche
H & H: Research and Training 43 / 94
EntityManager Consultation
EntityManager
Exemple avec utilisation de detach()
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
//on suppose que John Wick avec un num 10 existe
dans la BD
Personne p = [Link]([Link], 10);
[Link]("Travolta");
[Link](p); // p n’est plus gere par em
[Link]().begin();
[Link]();
[Link]().commit();
Personne p1 = [Link]([Link], 10);
[Link]("le nom est " + [Link]());
// affiche le nom est Wick
H & H: Research and Training 44 / 94
JPQL : Java Persistence Query Language
JPQL
Définition
JPQL est un langage de requêtes adapté à la spécification JPA
Inspiré du langage SQL (et HQL : Hibernate Query Language)
mais adapté aux entités JPA
Permet de manipuler les entités JPA et pas les tables d’une base
de données
Supporte des requêtes de type select, update et delete
H & H: Research and Training 45 / 94
JPQL : Java Persistence Query Language
JPQL
Définition
JPQL est un langage de requêtes adapté à la spécification JPA
Inspiré du langage SQL (et HQL : Hibernate Query Language)
mais adapté aux entités JPA
Permet de manipuler les entités JPA et pas les tables d’une base
de données
Supporte des requêtes de type select, update et delete
On manipule des entités et non pas des tables. Le nom des entités est
sensible à la casse.
H & H: Research and Training 45 / 94
JPQL : Java Persistence Query Language
JPQL
Exemple :
String str= "Select p from Personne as p";
Query query = [Link](str);
List <Personne> personnes = (List <Personne> ) query
.getResultList();
for (Personne p : personnes) {
[Link]([Link]() + " " + p.
getPrenom());
}
Explication
On sélectionne des objets p de type Personne
On peut aussi écrire "Select p from Personne p"
H & H: Research and Training 46 / 94
JPQL : Java Persistence Query Language
JPQL
Remarques
La requête JPQL précédente permet de sélectionner un objet
Il est tout de même possible de sélectionner seulement quelques
attributs d’un objet
Dans ce cas là, le résultat est un tableau contenant les champs
attributs sélectionnés
Et il est impossible de modifier (ou supprimer) les valeurs de ces
attributs sélectionnées
H & H: Research and Training 47 / 94
JPQL : Java Persistence Query Language
JPQL
Comme avec SQL, on peut faire des jointures
"select p from Personne p
join [Link] s
where [Link]= ’football’"
H & H: Research and Training 48 / 94
JPQL : Java Persistence Query Language
JPQL
Comme avec SQL, on peut faire des jointures
"select p from Personne p
join [Link] s
where [Link]= ’football’"
Équivalent en SQL
"select *
from Sport s, Personne Sport ps, Personne p
where [Link] = [Link] and [Link] = [Link]
and [Link] = ’football’"
H & H: Research and Training 48 / 94
JPQL : Java Persistence Query Language
JPQL
Comme avec SQL, on peut faire des jointures
"select p from Personne p
join [Link] s
where [Link]= ’football’"
Équivalent en SQL
"select *
from Sport s, Personne Sport ps, Personne p
where [Link] = [Link] and [Link] = [Link]
and [Link] = ’football’"
Explication
La jointure se fait avec join [Link] s
Le reste, c’est du SQL classique
H & H: Research and Training 48 / 94
JPQL : Java Persistence Query Language
JPQL
On peut également utiliser
group by
order by
having
distinct
les fonctions d’agrégation count, avg...
les requêtes imbriquées
les mots-clés all, (not) in, like, between, (not) null,
(not) exists...
H & H: Research and Training 49 / 94
JPQL : Java Persistence Query Language
JPQL
Attention aux collections
String str= "select p from Personne p
where [Link]= ’football’";
Query query = [Link](str);
[Link] est une collection
cette requête génère une erreur
H & H: Research and Training 50 / 94
Relation entre entités
Relation entre entités
Quatre (ou trois) relations possibles
OneToOne : chaque objet d’une première classe est en relation
avec un seul objet de la deuxième classe
OneToMany : chaque objet d’une première classe peut être en
relation avec plusieurs objets de la deuxième classe (la
réciproque est ManyToOne)
ManyToMany : chaque objet d’une première classe peut être en
relation avec plusieurs objets de la deuxième classe et
inversement
H & H: Research and Training 51 / 94
Relation entre entités OneToOne
Création de l’entité Adresse
}
package [Link]; public void setRue(String rue) {
[Link] = rue;
/** }
* Entity implementation class for
Entity: Adresse public String getCodePostal() {
* return [Link];
*/ }
@Entity
public class Adresse implements public void setCodePostal(String
Serializable { codePostal) {
[Link] = codePostal;
@Id }
private String rue;
private String codePostal; public String getVille() {
private String ville; return [Link];
private static final long }
serialVersionUID = 1L;
public void setVille(String
public Adresse() { ville) {
super(); [Link] = ville;
} }
public String getRue() { }
return [Link];
H & H: Research and Training 52 / 94
Relation entre entités OneToOne
Modifier l’entité Personne
@Entity
public class Personne implements Serializable {
@Id
private int num;
private String nom;
private String prenom;
@OneToOne(cascade={[Link], [Link]})
@JoinColumn(name="rue", referencedColumnName="rue", nullable=false)
private Adresse adresse;
// les getters/setters de chaque attribut
H & H: Research and Training 53 / 94
Relation entre entités OneToOne
Modifier l’entité Personne
@Entity
public class Personne implements Serializable {
@Id
private int num;
private String nom;
private String prenom;
@OneToOne(cascade={[Link], [Link]})
@JoinColumn(name="rue", referencedColumnName="rue", nullable=false)
private Adresse adresse;
// les getters/setters de chaque attribut
Notation
Personne : entité propriétaire
Adresse : entité inverse
H & H: Research and Training 53 / 94
Relation entre entités OneToOne
Relation entre entités
@OneToOne(cascade={[Link], CascadeType.
REMOVE})
Explication
cascade : ici on cascade les deux opérations PERSIST et
REMOVE qu’on peut faire de l’entité propriétaire à l’entité inverse
On peut cascader d’autres opérations telles que DETACH, MERGE,
et REFRESH...
on peut cascader toutes les opérations avec ALL
H & H: Research and Training 54 / 94
Relation entre entités OneToOne
Relation entre entités
@JoinColumn(name="rue", referencedColumnName="rue",
nullable=false)
Explication
Pour désigner la colonne dans Adresse qui permet de faire la
jointure
Pour dire que chaque personne doit avoir une adresse (donc on
ne peut avoir une personne sans adresse)
H & H: Research and Training 55 / 94
Relation entre entités OneToOne
Testons l’ajout d’une personne
EntityManagerFactory emf = Persistence.
createEntityManagerFactory("FirstJpaProject");
EntityManager em = [Link]();
Adresse a = new Adresse();
[Link]("Lyon");
[Link]("13015");
[Link]("Marseille");
Personne p = new Personne();
[Link](a);
[Link]("Ego");
[Link]("Paul");
EntityTransaction t =[Link]();
[Link]();
[Link](p);
[Link]();
[Link]("insertion reussie ");
[Link]();
[Link]();
H & H: Research and Training 56 / 94
Relation entre entités OneToOne
Testons l’ajout d’une personne
Sans la précision suivante
@OneToOne(cascade={[Link], CascadeType.
REMOVE})
Il fallait persister l’objet adresse avant l’objet personne
EntityTransaction t =[Link]();
[Link]();
[Link](a);
[Link](p);
[Link]();
H & H: Research and Training 57 / 94
Relation entre entités ManyToOne
ManyToOne
Exemple
Si on suppose que plusieurs personnes peuvent avoir la même
adresse
personne1
personne2
adresse
.
.
.
personneN
Many To One
H & H: Research and Training 58 / 94
Relation entre entités ManyToOne
ManyToOne
Il faut juste changer
@ManyToOne(cascade={[Link], CascadeType
.REMOVE})
@JoinColumn(name="rue", referencedColumnName="rue",
nullable=false)
H & H: Research and Training 59 / 94
Relation entre entités ManyToOne
ManyToOne
Il faut juste changer
@ManyToOne(cascade={[Link], CascadeType
.REMOVE})
@JoinColumn(name="rue", referencedColumnName="rue",
nullable=false)
Le reste
C’est pareil
H & H: Research and Training 59 / 94
Relation entre entités OneToMany
OneToMany
Exemple
Si on suppose qu’une personne peut avoir plusieurs adresses
adresse1
adresse2
personne
.
.
.
adresseN
One To Many
H & H: Research and Training 60 / 94
Relation entre entités OneToMany
OneToMany
Il faut changer
@OneToMany(cascade={[Link],
[Link]})
private List <Adresse> adresses = new ArrayList <
Adresse> ();
On peut aussi définir quand les objets de l’entité inverse (ici Adresse)
seront chargées dans l’entité propriétaire (ici Personne)
H & H: Research and Training 61 / 94
Relation entre entités OneToMany
OneToMany
Il faut ajouter dans l’annotation l’attribut fetch
@OneToMany(cascade={[Link],
[Link]}, fetch = [Link])
private List <Adresse> adresses = new ArrayList <
Adresse> ();
H & H: Research and Training 62 / 94
Relation entre entités OneToMany
OneToMany
Il faut ajouter dans l’annotation l’attribut fetch
@OneToMany(cascade={[Link],
[Link]}, fetch = [Link])
private List <Adresse> adresses = new ArrayList <
Adresse> ();
Deux valeurs possibles pour CONSTANTE
EAGER : les objets de l’entité Adresse en relation avec un objet
personne de l’entité Personne seront chargés au même temps.
LAZY (par défaut) : les objets de l’entité Adresse en relation avec
un objet personne de l’entité Personne seront chargés
seulement quand on fait [Link]’).
H & H: Research and Training 62 / 94
Relation entre entités OneToMany
OneToMany
N’oublions pas de supprimer ce code de l’entité Personne
@OneToOne(cascade={[Link], [Link]})
@JoinColumn(name="rue", referencedColumnName="rue", nullable=
false)
private Adresse adresse;
// les getters/setters de chaque attribut
H & H: Research and Training 63 / 94
Relation entre entités OneToMany
OneToMany
N’oublions pas de supprimer ce code de l’entité Personne
@OneToOne(cascade={[Link], [Link]})
@JoinColumn(name="rue", referencedColumnName="rue", nullable=
false)
private Adresse adresse;
// les getters/setters de chaque attribut
Ensuite
il faut générer le getter et le setter d’adresses
il faut aussi générer la méthode add et remove qui permettent d’ajouter ou de
supprimer une adresse pour un objet personne (Dans Source, choisir
Generate Delegate Methods).
Modifier le nom de la méthode add en addAdresse et remove en
removeAdresse
H & H: Research and Training 63 / 94
Relation entre entités OneToMany
OneToMany
N’oublions pas de supprimer ce code de l’entité Personne
@OneToOne(cascade={[Link], [Link]})
@JoinColumn(name="rue", referencedColumnName="rue", nullable=
false)
private Adresse adresse;
// les getters/setters de chaque attribut
Ensuite
il faut générer le getter et le setter d’adresses
il faut aussi générer la méthode add et remove qui permettent d’ajouter ou de
supprimer une adresse pour un objet personne (Dans Source, choisir
Generate Delegate Methods).
Modifier le nom de la méthode add en addAdresse et remove en
removeAdresse
H & H: Research and Training 63 / 94
Relation entre entités OneToMany
Testons l’ajout d’une personne
EntityManagerFactory emf = [Link]("
FirstJpaProject");
EntityManager em = [Link]();
Adresse a1 = new Adresse();
[Link]("Lyon");
[Link]("13015");
[Link]("Marseille");
Adresse a2 = new Adresse();
[Link]("Paradis");
[Link]("13003");
[Link]("Marseille");
Personne p1 = new Personne();
[Link]("Wick");
[Link]("John");
[Link](a1);
[Link](a2);
EntityTransaction t =[Link]();
[Link]();
[Link](p1);
[Link]();
[Link]("insertion reussie ");
[Link]();
[Link]();
H & H: Research and Training 64 / 94
Relation entre entités ManyToMany
ManyToMany
Exemple
Une personne peut pratiquer plusieurs sports
Un sport peut être pratiqué par plusieurs personnes
personne1 sport1
personne2 sport2
. .
. .
. .
personneN sportM
Many To Many
H & H: Research and Training 65 / 94
Relation entre entités ManyToMany
ManyToMany
Il faut juste changer
On commence par créer une entité Sport
On définit la relation ManyToMany (exactement comme les deux
relations précédentes) soit dans Personne soit dans Sport
H & H: Research and Training 66 / 94
Relation entre entités ManyToMany
Création de l’entité Sport
public class Sport implements Serializable {
@Id
private String nom;
private String type;
private static final long serialVersionUID = 1L;
public Sport() {
super();
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
[Link] = nom;
}
public String getType() {
return type;
}
public void setType(String type) {
[Link] = type;
}
}
H & H: Research and Training 67 / 94
Relation entre entités ManyToMany
Ajoutons le ManyToMany dans la classe Personne
@Entity
public class Personne implements Serializable {
@Id
private int num;
private String nom;
private String prenom;
@ManyToMany(cascade={[Link], [Link]})
private List <Sport> sports = new ArrayList <Sport> ();
// les getters/setters et constructeur
public List<Sport> getSports() {
return sports;
}
public void setSports(List<Sport> sports) {
[Link] = sports;
}
public boolean addSport(Sport arg0) {
return [Link](arg0);
}
public boolean removeSport(Object arg0) {
return [Link](arg0);
}
}
H & H: Research and Training 68 / 94
Relation entre entités ManyToMany
Testons tout ça
[Link]("individuel");
EntityManagerFactory emf = [Link]("collectif ou
Persistence. individuel");
createEntityManagerFactory(" [Link](s1);
FirstJpaProject"); [Link](s3);
EntityManager em = emf. [Link](s1);
createEntityManager(); [Link](s2);
Personne p1 = new Personne(); [Link](s3);
Personne p2 = new Personne(); EntityTransaction t =em.
[Link]("Wick"); getTransaction();
[Link]("John"); [Link]();
[Link]("Bob"); [Link](p1);
[Link]("Joe"); [Link](p2);
Sport s1 = new Sport(); [Link]();
Sport s2 = new Sport(); [Link]("insertion
Sport s3 = new Sport(); reussie ");
[Link]("football"); [Link]();
[Link]("tennis"); [Link]();
[Link]("box");
[Link]("collectif");
H & H: Research and Training 69 / 94
Relation entre entités ManyToMany
Cas particulier
Si la table association est porteuse de données
Par exemple : la relation (ArticleCommande) entre Commande et
Article
Il faut préciser la quantité de chaque article dans une commande
H & H: Research and Training 70 / 94
Relation entre entités ManyToMany
Cas particulier
Si la table association est porteuse de données
Par exemple : la relation (ArticleCommande) entre Commande et
Article
Il faut préciser la quantité de chaque article dans une commande
Solution
Créer trois entités Article, Commande et ArticleCommande
Définir la relation OneToMany entre Article et
ArticleCommande
Définir la relation ManyToOne entre ArticleCommande et
Commande
H & H: Research and Training 70 / 94
Relation entre entités ManyToMany
Remarques
Remarques
Les relations, qu’on a étudiées, sont unidirectionnelles
C’est à dire on peut faire [Link]();
Mais on ne peut faire [Link]();
H & H: Research and Training 71 / 94
Relation entre entités ManyToMany
Remarques
Remarques
Les relations, qu’on a étudiées, sont unidirectionnelles
C’est à dire on peut faire [Link]();
Mais on ne peut faire [Link]();
Solution
Rendre les relations bidirectionnelles
H & H: Research and Training 71 / 94
Relation entre entités ManyToMany
Relations bidirectionnelles : exemple
Modifier l’entité inverse Sport
/**
* Entity implementation class for Entity: Sport
*
*/
@Entity
public class Sport implements Serializable {
@Id
private String nom;
private String type;
private static final long serialVersionUID = 1L;
@ManyToMany(mappedBy="sports")
private List <Personne> personnes = new ArrayList <Personne> ();
// ajouter les getter, setter, add et remove
}
mappedBy
fait référence à l’attribut sports dans la classe Personne
H & H: Research and Training 72 / 94
Relation entre entités ManyToMany
Relations bidirectionnelles : exemple
Modifier aussi l’entité propriétaire Personne
@Entity
public class Personne implements Serializable {
...
public void add(Sport s) {
// ajouter this a la liste des personnes de ce sport
[Link](this);
[Link](s);
}
public void remove(Sport s) {
// supprimer this de la liste des personnes de ce sport
[Link](this);
[Link](s);
}
La même chose à faire dans Sport pour la liste personnes. Attention aux boucles infinies.
H & H: Research and Training 73 / 94
Relation entre entités ManyToMany
Relations bidirectionnelles : exemple
Ainsi, on peut faire :
[Link](s1);
[Link](s3);
[Link](s1);
[Link](s2);
[Link](s3);
EntityTransaction t = [Link]();
[Link]();
[Link](p1);
[Link](p2);
[Link]();
[Link]([Link]().get(0).getNom()
);
H & H: Research and Training 74 / 94
Relation entre entités ManyToMany
Relations bidirectionnelles : exemple
Ainsi, on peut faire :
[Link](s1);
[Link](s3);
[Link](s1);
[Link](s2);
[Link](s3);
EntityTransaction t = [Link]();
[Link]();
[Link](p1);
[Link](p2);
[Link]();
[Link]([Link]().get(0).getNom()
);
affiche Wick
H & H: Research and Training 74 / 94
Relation entre entités ManyToMany
Remarques
Pour définir une relation bidirectionnelle entre deux entités
si dans l’entité propriétaire la relation définie est OneToMany,
alors dans l’entité inverse la relation sera ManyToOne, et
inversement.
si dans l’entité propriétaire la relation définie est OneToOne, alors
dans l’entité inverse la relation sera aussi OneToOne.
si dans l’entité propriétaire la relation définie est ManyToMany,
alors dans l’entité inverse la relation sera aussi ManyToMany.
H & H: Research and Training 75 / 94
Relation entre entités Inheritance
L’association d’héritage
Trois possibilités avec l’héritage
SINGLE TABLE
TABLE PER CLASS
JOINED
H & H: Research and Training 76 / 94
Relation entre entités Inheritance
L’association d’héritage
Trois possibilités avec l’héritage
SINGLE TABLE
TABLE PER CLASS
JOINED
Exemple
Une classe mère Personne
Deux classes filles Etudiant et Enseignant
H & H: Research and Training 76 / 94
Relation entre entités Inheritance
L’association d’héritage
Pour indiquer comment transformer les classes mère et filles en tables
Il faut utiliser l’annotation @Inheritance
H & H: Research and Training 77 / 94
Relation entre entités Inheritance
L’association d’héritage
Tout dans une seule table
Dans la classe mère on ajoute
@Inheritance(strategy=[Link] TABLE)
H & H: Research and Training 78 / 94
Relation entre entités Inheritance
L’association d’héritage
Exemple
Et pour distinguer un étudiant d’un enseignant, d’une personne
@DiscriminatorColumn(name="TYPE PERSONNE") dans la
classe mère,
@DiscriminatorValue(value="PERS") dans la classe
Personne,
@DiscriminatorValue(value="ETU") dans la classe
Etudiant et
@DiscriminatorValue(value="ENS") dans la classe
Enseignant.
Dans la table personne, on aura une colonne TYPE PERSONNE qui
aura comme valeur soit PERS, soit ETU soit ENS.
H & H: Research and Training 79 / 94
Relation entre entités Inheritance
L’association d’héritage
Exemple avec une table pour chaque entité
@Inheritance(strategy=[Link] PER CLASS) :
Chaque entité sera transformée en table.
H & H: Research and Training 80 / 94
Les classes incorporables
Les classes incorporables : pas de table correspondante en BD
Et si on déplace les attributs nom et prénom dans une nouvelle classe NomComplet
@Embeddable
public class NomComplet {
private String nom;
private String prenom;
public String getNom() {
return nom;
}
public void setNom(String nom) {
[Link] = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
[Link] = prenom;
}
@Override
public String toString() {
return "NomComplet [nom=" + nom + ", prenom=" + prenom + "]";
}
}
H & H: Research and Training 81 / 94
Les classes incorporables
Les classes incorporables : pas de table correspondante en BD
L’entité Personne devient ainsi :
@Entity
public class Personne {
@Id
@GeneratedValue (strategy=[Link])
private int num;
private NomComplet nomComplet;
public int getNum() {
return num;
}
public void setNum(int num) {
[Link] = num;
}
public NomComplet getNomComplet() {
return nomComplet;
}
public void setNomComplet(NomComplet nomComplet) {
[Link] = nomComplet;
}
H & H: Research and Training 82 / 94
Les classes incorporables
Les classes incorporables : pas de table correspondante en BD
Pour persister une personne
Personne personne = new Personne();
NomComplet nomComplet = new NomComplet();
[Link]("travolta");
[Link]("john");
[Link](nomComplet);
EntityTransaction t =[Link]();
[Link]();
[Link](personne);
[Link]();
H & H: Research and Training 83 / 94
Les classes incorporables
Les classes incorporables : pas de table correspondante en BD
Pour persister une personne
Personne personne = new Personne();
NomComplet nomComplet = new NomComplet();
[Link]("travolta");
[Link]("john");
[Link](nomComplet);
EntityTransaction t =[Link]();
[Link]();
[Link](personne);
[Link]();
Il n’y aura pas de table NomComplet, les attributs nom et prénom
seront transformés en colonne dans la table Personne
H & H: Research and Training 83 / 94
Les méthodes callback
Les évènements
Cycle de vie d’une entité
Le cycle de vie de chaque objet d’une entité JPA passe par trois
événements principaux
création (avec persist())
mise à jour (avec flush())
suppression (avec remove())
H & H: Research and Training 84 / 94
Les méthodes callback
Les évènements
Une méthode callback
Une méthode callback est une méthode qui sera appelée avant
ou après un évènement survenu sur une entité
On utilise les annotations pour spécifier quand la méthode
callback sera appelée
H & H: Research and Training 85 / 94
Les méthodes callback
Les évènements
Une méthode callback
Une méthode callback est une méthode qui sera appelée avant
ou après un évènement survenu sur une entité
On utilise les annotations pour spécifier quand la méthode
callback sera appelée
C’est comme les triggers en SQL
H & H: Research and Training 85 / 94
Les méthodes callback
Les annotations
@PrePersist : avant qu’une nouvelle entité soit persistée.
@PostPersist : après l’enregistrement de l’entité dans la base
de données.
@PostLoad : après le chargement d’une entité de la base de
données.
@PreUpdate : avant que la modification d’une entité soit
enregistrée en base de données.
@PostUpdate : après que la modification d’une entité est
enregistrée en base de données.
@PreRemove : avant qu’une entité soit supprimée de la base de
donnée.
@PostRemove : après qu’une entité est supprimée de la base de
donnée.
H & H: Research and Training 86 / 94
Les méthodes callback
Les méthodes callback
Exemple : l’entité Personne
public class Personne implements Serializable {
@Id
private int num;
private String nom;
private String prenom;
private int nbrMAJ=0; // pour calculer le nombre de
modification
public int getNbrMAJ() {
return nbrMAJ;
}
public void setNbrMAJ(int nbrMAJ) {
[Link] = nbrMAJ;
}
@PostUpdate
public void updateNbrMAJ() {
[Link]++;
}
// les autres getters, setters et constructeur
H & H: Research and Training 87 / 94
Les méthodes callback
Les méthodes callback
Personne p1 = new Personne();
[Link]("Wick");
[Link]("John");
[Link]().begin();
[Link](p1);
[Link]().commit();
[Link]("nbrMAJ = " + [Link]());
// affiche nbrMAJ = 0
[Link]("Travolta");
[Link]().begin();
[Link]();
[Link]().commit();
[Link]("Abruzzi");
[Link]().begin();
[Link]();
[Link]().commit();
[Link]("nbrMAJ = " + [Link]());
// affiche nbrMAJ = 2
H & H: Research and Training 88 / 94
Utilisation de l’API JPA dans un projet JEE
JEE & JPA
Étapes
Créer un nouveau projet JEE (en Allant dans File, ensuite New
et chercher Dynamic Web Project)
Saisir le nom du projet (dans Project name:)
Dans l’onglet Configuration, cliquer sur Modify...
Cocher la case JPA et choisir la dernière version de JPA
Cliquer sur Next et configurer les options de JPA
Générer le [Link] du projet JEE
Valider
H & H: Research and Training 89 / 94
Utilisation de l’API JPA dans un projet JEE
JEE & JPA
Remarques
Ainsi, on a créé un projet JEE dans lequel on peut créer, utiliser et
manipuler des entités JPA
Sans cette configuration, nous ne pourrons pas utiliser l’API JPA
H & H: Research and Training 90 / 94
Utilisation de l’API JPA dans un projet Maven
Maven & JPA
Étapes
Créer un nouveau projet Maven
Ajouter les liens et les répertoires qui manquent à ce projet
Ajouter JPA
H & H: Research and Training 91 / 94
Utilisation de l’API JPA dans un projet Maven
Maven & JPA
Étapes
Créer un nouveau projet Maven
Ajouter les liens et les répertoires qui manquent à ce projet
Ajouter JPA
Création d’un projet Maven
Aller dans File > New et chercher Maven Project
Choisir un projet maven-archetype-webapp
Remplir le champs Group Id par [Link]
Remplir le champs Artifact Id par JeeJpaMavenProject
Valider
H & H: Research and Training 91 / 94
Utilisation de l’API JPA dans un projet Maven
JEE & JPA
Si [Link] est signalé en rouge
Faire clic droit sur le nom du projet
Choisir Properties
Chercher puis sélectionner Targeted Runtimes
Cocher la case Apache Tomcat vX.X puis cliquer sur Apply
and Close
H & H: Research and Training 92 / 94
Utilisation de l’API JPA dans un projet Maven
JEE & JPA
S’il n’y a pas de src/main/java dans Java Resources
Faire clic droit sur le nom du projet
Aller dans Build Path > Configure Build Path...
Cliquer sur Order and Export
Cocher les trois case Maven Dependencies, Apache Tomcat
vX.X et JRE System Library
Cliquer sur Apply and Close
H & H: Research and Training 93 / 94
Utilisation de l’API JPA dans un projet Maven
JEE & JPA
Ajouter JPA
Faire un clic droit sur le nom du projet et aller dans Properties
Chercher Project Facets
Cocher la case JPA
Cliquer sur le lien qui apparaı̂t (Further configuration
available...) pour ajouter les données sur EclipseLink et la
connexion
Cliquer sur Apply and Close
H & H: Research and Training 94 / 94