Spring Boot : JPA
Pr. Y. EL GHAYAM
Définition
– JPA (Java Persistence API) est une spécification créée par Sun pour standardiser
le mapping Objet relationnel ORM (Object Relational Mapping).
– Un ORM est un framework qui permet de créer une liaison entre un modèle objet
et un modèle relationnel de base de données.
– Il fournit les fonctionnalités suivantes :
●
génération des requêtes SQL de CRUD en utilisant des méthodes.
●
prise en charge des contraintes de la base sous forme des dépendances entre
objets.
●
support pour la construction de requêtes complexes par programmation.
– JPA définit un ensemble d’interfaces, de classes abstraites et d’annotations qui
permettent la description du mapping objet relationnel
– Il existe plusieurs implémentation de JPA:
– Hibernate
– Toplink
– IBatis
– EclipseLink
– L’utilisation de JPA permet à votre application d’être indépendante du Framework
ORM utilisé
Définition
Intégration de JPA dans un projet Spring Boot
– Spring est un Framework qui assure l’inversion de contrôle.
– Spring s’occupe du code technique de la configuration de JPA.
– JPA peut être intégré dans un projet en utilisant le fichier [Link] :
#indiquer le serveur de BD et le nom de la base
[Link]=jdbc:mysql://localhost:3306/ma_base
#le login et le mot de passe pour pouvoir accéder à une base.
[Link] = root
[Link] =mot_de_passe
#Montrer les requetes sql générées
[Link]-sql = true
#générer une nouvelle base de données ou seulement la mettre à jour : create / update
[Link]-auto = update
#indiquer la version de sql utilisé
[Link] = [Link].MySQL5Dialect
Utilisation de JPA
– JPA peut être intégré en utilisant des annotations :
– @Entity : Indique que la classe est persistante est correspond à une table dans la
base de donées. Annotation obligatoire.
– @Table : Définir le nom de la table concernée par le mapping. Par défaut c’est le
nom de la classe qui sera considérée
– @Column : Associer un champ de la colonne à la propriété. Par défaut c’est le
nom de la propriété qui sera considérée.
– @Id : Associer un champ de la table à la propriété en tant que clé primaire.
Annotation obligatoire.
– @GeneratedValue : Demander la génération automatique de la clé primaire au
besoin.
– @Transient : Demander d’ignorer un champ lors du mapping.
– @OneToMany, @ManyToOne : Pour décrire une association de type un à
plusieurs et plusieurs à un.
– @JoinedColumn : Pour décrire une clé étrangère dans une table.
– @ManyToMany : Pour décrire une association plusieurs à plusieurs.
Utilisation de JPA
– Exemple :
package dao;
import [Link]; import
[Link].*;
@Entity
@Table(name="PRODUITS")
public class Produit implements Serializable {
@Id
@GeneratedValue(strategy=[Link])
@Column(name="REF", nullable=false,length=128)
private Long reference;
@Column(name="DES")
private String designation;
private double prix;
private int quantite;
@Temporal([Link]) // TIME , TIMESTAMP
private Date dateCreation
// Constructeur par défaut
// Getters et Setters
}
Utilisation de JPA : les associations
Utilisation de JPA : les associations
– OneToMany - ManyToOne
@Entity
public class Patient {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private String nom;
private String email;
@OneToMany(mappedBy = "patient")
private Collection<RendezVous> rendezVous;
}
@Entity
public class RendezVous {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private Date dateRendezVous;
@ManyToOne
private Medecin medecin;
@ManyToOne
private Patient patient;
@OneToOne
private Consultation consultation;
}
Utilisation de JPA : les associations
– OneToOne - ManyToOne : patient - Rendez-vous
@Entity
public class Consultation {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private Date dateConsultation;
private String rapportConsultation;
private double prixConsultation;
@OneToOne(mappedBy = "consultation")
// @JoinColumn(name=”RendezVous_id”)
private RendezVous rendezVous;
}
@Entity
public class RendezVous {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private Date dateRendezVous;
@ManyToOne
private Medecin medecin;
@ManyToOne
private Patient patient;
@OneToOne
private Consultation consultation;
}
Utilisation de JPA : les associations
– ManyToMany : Utilisateurs Groupe
Id : Long * * Id : Long
usename : String groupName: String
password : String
@Entity
public class Utilisateur {
@Id @GeneratedValue(strategy = [Link])
private Long id;
@Column(unique = true)
private String userName;
private String password;
@ManyToMany(mappedBy = "utilisateurs",fetch = [Link]) // [Link]
private Collection<Groupe> groupes=new ArrayList<>();
}
@Entity
public class Groupe {
@Id @GeneratedValue(strategy = [Link])
private Long id;
@Column(unique = true)
private String groupName;
@ManyToMany(fetch = [Link])
private Collection<Utilisateur> utilisateurs=new ArrayList<>();
}
Utilisation de JPA : héritage
– Différentes stratégies de Mapping de l’héritage
●
Une seule table par hiérarchie (SINGLE_TABLE) :
●
Une table pour chaque classe concrète (TABLE_PER_CLASS)
●
Une table pour la classe parente et une table pour chaque classe fille (JOINED_TABLE)
Personne SINGLE_TABLE : PERSONNES
ID TYP NOM DATE_NAISSAN NOT MAIETRE
Id : Long
E CE E
Nom: String
dateNaissance : 1 ET N1 d1 15 NULL
Date
2 PROF N2 d2 NULL MATH
Etudiant Enseignant TABLE_PER_CLASS
note: double matiere: String ETUDIANTS
ID NOM DATE_NAISSAN NOT
CE E
JOINED_TABLE 1 N1 d1 15
ETUDIANTS ENSEIGNANTS
NOT #ID
E
PERSONNES ID NOM DATE_NAISSAN MATIER
ID NO DATE_NAISSA CE E
15 1 M NCE
2 N2 d2 MATH
ENSEIGNANTS 1 N1 d1
MATIE #ID
RE 2 N2 d2
MATH 2
Utilisation de JPA : héritage
– SINGLE_TABLE
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TYPE",length = 4)
public abstract class Personne {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private String nom;
private Date dateNaissance;
}
@Entity
@DiscriminatorValue("ETUD")
public class Etudiant extends Personne {
private double note;
}
@Entity
@DiscriminatorValue("PROF")
public class Enseignant extends Personne {
private String matiere;
}
public interface PersonneRepository extends JpaRepository<Personne,Long> {
}
@Autowired
private PersonneRepository personneRepository;
Etudiant etudiant=new Etudiant();
Enseignant enseignant=new Enseignant();
Utilisation de JPA : héritage
– TABLE_PER_CLASS
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Personne {
@Id @GeneratedValue(strategy =
[Link])
private Long id;
private String nom;
private Date dateNaissance;
}
@Entity
public class Etudiant extends Personne {
private double note;
}
@Entity
public class Enseignant extends Personne {
private String matiere;
}
public interface PersonneRepository extends JpaRepository<Personne,Long> {
}
@Autowired
private PersonneRepository personneRepository;
Etudiant etudiant=new Etudiant();
Enseignant enseignant=new Enseignant();
Utilisation de JPA : héritage
– JOINED TABLE
@Entity
@Inheritance(strategy = [Link])
public abstract class Personne {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private String nom;
private Date dateNaissance;
}
@Entity
public class Etudiant extends Personne {
private double note;
}
@Entity
public class Enseignant extends Personne {
private String matiere;
}
public interface PersonneRepository extends JpaRepository<Personne,Long> {
}
@Autowired
private PersonneRepository personneRepository;
Etudiant etudiant=new Etudiant();
Enseignant enseignant=new Enseignant();
Utilisation de JPA : accéder à la base
– L’accès à la base se fait par la création d’une interface étendant un Repository.
●
Permet d’analyser les différentes méthodes et de générer les requêtes; les requêtes
de CRUD.
●
Permet aussi de personnaliser les requêtes.
– Les méthodes par défaut :
●
List<Entite> findAll() : retourner toutes les entités,
●
List<Entite> findAllById(List<Integer> Ids) : retourner un ensemble des entiés
indiquées par leurs Id,
●
Optional<Entite> findById(Integer Id) : retourner une entié selon son Id,
●
Void deleteAll() : enlever toutes les entités ,
●
boolen deleteById(Integer Id) enlever une entité indiquée par son Id,
●
Entite save(Entite E) enregistrer l’entité E,
●
List<Entite> saveAll(List<Entite> entities) : enregistrer unensemble des entités.
●
Long count() : retourne le nombre des entités.
●
boolean existsById(Integer Id) : vérifie l’existence d’une entité.
Utilisation de JPA : accéder à la base
– La personnalisation des méthodes est réalisée en respectant une certaine convention
– Pour une entité définie par l’attribut Nom et Age, on peut définir dans le Reppository
correspondant :
●
Entite findByNom(String nom) : retourner l’entité indiqué par son nom;
●
List<Entite> findByNom(String nom) : retourner la liste des entités indiquées par
son nom.
●
List<Entite> findByAgeBetween(int a1, int a2) : retourner les entités ayant l’age
entre a1 et a2.
●
List<Entite> findTop3ByAge() : retourner les 3 premières entités triées selon
l’age.
●
List<Entite> findByNomAndAge(String nom, int age) : retourner les entités
indiquées par le nom et l’age.
Utilisation de JPA : accéder à la base
– Les différents mots clés possibles :
Utilisation de JPA : accéder à la base
– Utiliser @Query pour des requêtes compliquées :
– En utilisant la notation orienté-objet :
@Query("select cl from Client cl
join Commande [Link]
where [Link] = ?1 or [Link] = ?2")
User maRequete(@Param("lastname") String lastname, @Param("firstname") String ville);
– En utilisant la syntaxe de Sql :
@Query(value ="select cl from client cl
join commande cmd on [Link] = cmd.client_id
where [Link] = ?1 or [Link] = ?2", NativeQuery = “true”)
“true”
User maRequete(@Param("lastname") String lastname, @Param("firstname") String firstname);