Vous êtes sur la page 1sur 37

La spécification JPA 2.

1
Les entités
Septembre 2019

Hend FOURATI
hend.fourati@esprit.tn
1
Bureau E204
 JDBC
Plan
 ORM
 Introduction JPA
 La sérialisation
 Les entités JPA
 Basic Types
 Le type java.util.Date
 Stratégies d’auto génération des IDs
 Les énumérations
 Classe Embeddable
 Clé composite
 Clé composite avec @IdClass
 Clé composite avec @EmbeddedId
 Héritage
 Héritage single Table (par défaut)
 Persistence.xml
2
 Création de la premiere entité
JDBC
L’utilisation de l’API JDBC était une solution pour les développeurs java pour
unifier l’accès à une base de données SQL.

Inconvénients :
 Pas de séparation entre le code technique et le code métier
 utilisation du langage SQL rend la couche d’accès aux données difficilement
maintenable.

3
ORM
L'ORM (Object-Relational Mapping) est un concept faisant le lien entre le monde
de la base de données et le monde de la programmation orienté objet.

4
ORM

Sans
ORM

Avec
ORM

5
Introduction JPA
JPA est une spécification Java EE basée sur le concept ORM (Object Relational
mapping).

l'utilisation de JPA nécessite un fournisseur de persistance qui implémente les


les spécifications JPA.

Il y a plusieurs fournisseurs de persistance qui implémentent la spécification JPA,


tel que, Hibernate, Toplink, datanucleus...

Dans ce cours nous allons utiliser Hibernate comme implémentation de la


spécification JPA.

6
Introduction JPA
Les principaux avantages de JPA sont les suivants :

● JPA peut être utilisé par toutes les applications Java (Java SE ou Java EE).

● Mapping O/R (objet-relationnel) avec les tables de la BD, facilitée par les

Annotations.

● Un langage de requête objet standard JPQL pour la récupération des objets.

● Possibilité de génération automatique du schéma de la base de données à

partir des entités.


7
La sérialisation
Le mécanisme de sérialisation consiste à convertir un objet en une suite de bits.

Nous pouvons ainsi sérialiser les objets sur disque, sur une connexion réseau
(notamment Internet), sous un format indépendant des systèmes d'exploitation.

Java fournit un mécanisme simple, transparent et standard de sérialisation des


objets via l'implémentation de l'interface java.io.Serializable.

8
Les entités JPA
Une entité JPA est une classe JAVA qui doit satisfaire les conditions suivantes :

 Être déclaré avec l'annotation @Entity.

 Posséder au moins une propriété déclarée comme identité de l’entité avec


l'annotation @Id.

 Implémenter l’interface java.io.Serializable.

 Tous les attributs doivent être « private » ou « protected »et avoir


obligatoirement des accesseurs et des mutateurs (les méthodes getters et
setters).
9
Les entités JPA
Le fournisseur de persistance accédera à la valeur d’une variable d’instance:
-Soit en accédant directement à la variable d’instance
-Soit en passant par ses accesseurs (getter ou setter)
Le constructeur vide existe par défaut si aucun constructeur n'existe dans la classe.

10
Les entités JPA
Pour donner à la table un autre nom que le nom de la classe, il faut ajouter une
annotation @Table

Pour donner à une colonne de la table un autre nom que le nom de l’attribut
correspondant, il faut ajouter une annotation @Column

11
Basic Types
 Java primitive types (boolean, int, etc)
 wrappers for the primitive types (java.lang.Boolean, java.lang.Integer, etc)
 java.lang.String
 java.math.BigInteger
 java.math.BigDecimal
 java.util.Date
 java.util.Calendar
 java.sql.Date
 java.sql.Time
 java.sql.Timestamp
 byte[] or Byte[]
 char[] or Character[]
 enums
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_G
uide.html#basic
12
Les dates
Lorsqu'une entité jpa a un attribut de type temporel (Calendar ou Date de
java.util), il est obligatoire d'indiquer de quel type temporel est cet attribut par une
annotation @Temporal.

 TemporalType.DATE : la date va être sauvegardée dans la base de données sous forme d’une date
(jour, mois, année)
 TemporalType.TIMESTAMP : la date va être sauvegardée dans la base de données sous forme
d’une date (jour, mois, année) + heure à la microseconde.
 TemporalType.TIME : Un temps sur 24 heures (heures, minutes, secondes à la milliseconde près).

13
Stratégies d’auto génération des IDs
Si l’ID est de type String, int, byte, char, double, float, long ou short, l’insertion de
l’id peut se faire automatiquement par l’une des stratégies suivantes :
IDENTITY : La génération de la clé primaire se fait à partir d’une Identité propre au SGBD. Il utilise un
type de colonne spéciale à la base de données.
Exemple pour MySQL, il s’agit d’un AUTO_INCREMENT.
SEQUENCE : la génération de la clé primaire est garantie par le fournisseur de persistance (hibernate),
une séquence de clé primaire pour un schéma de base de données défini dans une table
hibernate_sequence.
TABLE : la génération des clés primaires est garanti par le fournisseur de persistance (hibernate), une
séquence de clés primaires par table définie dans une table hibernate_sequences, cette table contient
deux colonnes : une pour le nom de la séquence et l’autre pour la prochaine valeur.

14
Les énumérations
EnumType.String : Si la valeur de l’attribut va être stockés dans la base de données sous forme de
String qui représente la valeur de l’énumération.

EnumType.Ordinal: Si la valeur de l’attribut va être stockés dans la base de données sous forme de
Integer qui représente la valeur de l’énumération.

15
Classe Embeddable
Il existe aussi des classes « insérées » ou « incorporées » (embedded) dont les
données n’ont pas d’identité dans la BD mais sont insérées dans une des tables
associées à une entité persistante

16
Clé composite
Pas recommandé, mais une clé primaire peut être composée de plusieurs colonnes.

• Peut arriver quand la BD existe déjà ou quand la classe correspond à une table
d’association (association M:N avec information )

2 solutions :
-@IdClass
-@EmbeddedId et @Embeddable

Dans les 2 cas, la clé primaire doit être représentée par une classe Java dont les
attributs correspondent aux composants de la clé primaire.

La classe doit être public, posséder un constructeur sans paramètre, être


sérialisable et redéfinir equals et hashcode.

17
Clé composite avec @EmbeddedId

@EmbeddedId correspond au cas où la


classe entité comprend un seul attribut
annoté @EmbeddedId

• La classe clé primaire est annoté par


@Embeddable

18
Clé composite avec @IdClass
-@IdClass correspond au cas où la classe
entité comprend plusieurs attributs annotés
par @Id

La classe entité est annotée par @IdClass


qui prend en paramètre le nom de la classe
clé primaire

-La classe clé primaire n’est pas annotée


(comme @Embeddable) ; ses attributs ont
les mêmes noms et mêmes types que les
attributs annotés @Id dans la classe entité

19
Héritage
Pour représenter un modèle hiérarchique dans un modèle relationnel, JPA propose alors trois
stratégies possibles :

1. Une seule table unique pour l'ensemble de la hiérarchie des classes. L'ensemble des
attributs de toute la hiérarchie des entités est mis à plat et regroupé dans une seule table (il
s'agit d'ailleurs de la stratégie par défaut).
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

2. Une table pour chaque classe concrète. Chaque entité concrète de la hiérarchie est
associée à une table. @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

3. Jointure entre sous-classes. Dans cette approche, chaque entité de la hiérarchie, concrète
ou abstraite, est associée à sa propre table. Ainsi, nous obtenons dans ce cas une séparation
des attributs spécifiques de la classe fille par rapport à ceux de la classe parente. Il existe alors,
une table pour chaque classe fille, plus une table pour la classe parente.
@Inheritance(strategy=InheritanceType.JOINED)

20
Héritage single Table (par défaut)
La colonne Discriminator est gérée par JPA, certes une configuration personnalisée
est permise pour le nom de la colonne discriminateur et la valeur de discrimination.

Configuration par défaut Configuration personnalisée 21


persistence.xml

 Le fichier persistence.xml doit être stocké dans le


répertoire META-INF
 Il contient un ou plusieurs tags <persistence-unit>
 Il contient les informations sur la connexion à la base
de données à utiliser.

22
Création de la premiere entité
Etape 1: Création d’une base de données:

1) Installer le serveur Mysql

2) Créer une base de données qui s’appelle “imputation”

23
Etape 2: Création de la datasource

• Une datasource est une structure de données utilisée pour décrire une connexion (URL,
Driver, UserName, …) à une source de donnée (base de données). Exemple :

<datasource jta="true" jndi-name="java:/ImputationDS" pool-


name="ImputationDS" enabled="true" use-ccm="true">
<connection-url>jdbc:mysql://localhost:3306/imputation</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver>mysql</driver>
<security>
<user-name>root</user-name>
</security>
</datasource>

24
Création de la datasource http://127.0.0.1:10990 (admin / adminwildfly)
• Aller dans le fichier standalone.xml (de WildFly), et vérifier si vous avez une DataSource qui
permet de vous connecter à votre base de données « imputation » ?
• Nous allons créer cette DataSource. Il y a deux façons :
• Méthode 1 : Modifier directement el fichier standalone.xml (risque d’erreur, à ne pas faire).
• Méthode 2 (conseillée) : Utiliser l’interface d’administration de WildFly. Voici la démarche :
• Démarrer votre WildFly (Plugin Server sur Eclipse), dans les logs vous trouverez l’URL de la
console d’administration :
WFLYSRV0051: Admin console listening on http://127.0.0.1:10990
• Ouvrir la console d’administration : http://127.0.0.1:10990 (login admin / mot de passe
adminwildfly)
• Configuration -> Subsystems -> Datasources -> View -> Add -> MySQL Datasource -> Name
: ImputationDS JNDI Name java:/ImputationDS -> Detected Driver -> mysql ->
jdbc:mysql://localhost:3306/imputation (ajouter login et password) -> Test Connection

25
Création de la datasource http://127.0.0.1:10990 (admin / adminwildfly)

26
Création de la datasource http://127.0.0.1:10990 (admin / adminwildfly)

Revérifier standalone.xml :

<datasource jta="true" jndi-name="java:/ImputationDS" pool-name="ImputationDS"


enabled="true" use-ccm="true">
<connection-url>jdbc:mysql://localhost:3306/imputation</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver>mysql</driver>
<security>
<user-name>root</user-name>
</security>
</datasource>

27
Création de la première entité:

• Nous allons utiliser un archétype de projet déjà prêt.

• Ajouter l’URL du catalogue de projets à votre Eclipse (Voir slide suivant) :

http://repo.maven.apache.org/maven2/archetype-catalog.xml

• Assurez-vous d’avoir Internet

• Window – Preferences – Maven – Archetypes – Add Remote Archetype


• Entrez l’URL ci-dessus et un nom de ce dépôt d’archetypes)
• Cliquer sur Verify pour vous assurer que Eclipse a téléchargé les archetypes
• Cliquer sur Enable All pour activer l’utilisation de ce dépôt.

28
Création de la datasource http://127.0.0.1:10990 (admin / adminwildfly)

29
Création d’une première Entité

• http://repo.maven.apache.org/maven2/archetype-catalog.xml

30
Création d’une première Entité
• Créer un nouveau projet de type Maven, et NE cochez PAS la case « skip archetype »
, car justement nous allons utiliser un template de projet.

• Choisissez le template : wildfly-javaee7-webapp-ear-blank-archetype

31
Création de la datasource http://127.0.0.1:10990 (admin / adminwildfly)
• Modifier les entrées suivantes dan le pom.xml su Projet parent :

<version.wildfly>11.0.0.Final</version.wildfly>
………………….
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>

• Faire un bouton droit sur le projet parent et faire un Maven -> Update Project

• Dans le pom du projet web, ajouter la dépendance suivante :


<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency> 32
Création de la datasource http://127.0.0.1:10990 (admin / adminwildfly)
• Dans cette partie, on va travailler que sur le projet EJB :
• Aller au projet EJB et mettez à jour le fichier persistence.xml sous <src/main/resources/META-INF>
pour pointer vers votre DataSource :
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="imputation-ejb">
<jta-data-source>java:/ImputationDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
</properties>
</persistence-unit>
</persistence> 33
Création d’une première Entité

• Créer un package tn.esprit.imputation.entity sous <src/main/java>

• Créer l’entité utilisateur avec les attributs nom, prenom et adresse email
• N’oublier pas de mettre les annotations nécessaires
• Donner des nom personnalisés à la table et aux colonnes (différents des noms par défaut)
• Voici le résultat final souhaité :

34
Création d’une première Entité

35
Création d’une première Entité

• Déployer le projet sur WildFly et voir les logs


21:00:59,914 INFO [java.sql.DatabaseMetaData] (ServerService Thread Pool -- 66)
HHH000262: Table not found: T_UTILISATEUR
21:00:59,945 INFO [org.hibernate.tool.hbm2ddl.SchemaUpdate] (ServerService Thread
Pool -- 66) HHH000232: Schema update complete

• Vérifier dans la base de données :


• show tables;
• describe t_utilisateur;

• Si vous voulez recommencer le test de création, supprimer la table avec : drop table
t_utilisateur;

36
Création d’une première Entité
@Entity
@Table(name="T_UTILISATEUR")
public class Utilisateur implements Serializable {
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column(name="UT_ID")
int id;
@Column(name="UT_NOM")
String nom;
@Column(name="UT_PRENOM")
String prenom;
@Column(name="UT_ADRESS_MAIL")
String adresseMail;
public Utilisateur() {}
public String getNom() {return nom;}
public void setNom(String nom) {this.nom = nom;}
public String getPrenom() {return prenom;}
public void setPrenom(String prenom) {this.prenom = prenom;}
public String getAdresseMail() {return adresseMail;}
public void setAdresseMail(String adresseMail) {this.adresseMail = adresseMail;}
37
}