(Jakarta Persistence
Total Page:16
File Type:pdf, Size:1020Kb
Plan de ce cours Présentation de JPA JPA Entité Gestionnaire d’entités (Jakarta Persistence API) Compléments sur les entités : pour Jakarta EE identité, associations, héritage Requêtes, JPQL ITU - Université Côte d’Azur Modification en volume Richard Grin Concurrence Version O 1.37 – 10/3/20 Adaptation à une base préexistante Bibliographie R. Grin JPA page 2 1 2 JPA Spécification pour la persistance des objets Java dans une base de données (BD) relationnelle ORM, Object-Relational mapping, fait Présentation de JPA correspondre le monde relationnel et le monde des objets Au-dessus de JDBC ; donc un driver JDBC du SGBD doit être installé sur le serveur d’application ou dans l’application Ce support étudie JPA dans Jakarta EE mais JPA peut aussi être utilisé avec Java SE R. Grin JPA page 3 R. Grin JPA page 4 3 4 Principales propriétés de JPA Fournisseur de persistance Des appels simples permettent de gérer la L’utilisation de JPA nécessite un fournisseur persistance, par exemple « persist(objet) » de persistance qui implémente les classes et pour rendre un objet persistant interfaces de l’API Les données de la base de données relationnelle EclipseLink et Hibernate sont des fournisseurs sont traitées avec une vision objet, en utilisant les de persistance classes Java entités R. Grin JPA page 5 R. Grin JPA page 6 5 6 1 Entité Exemple d’entité – identificateur et attributs Classe dont les instances peuvent être persistantes @Entity Clé primaire Annotée par @Entity public class Departement { dans la base – obligatoire « entité » peut aussi désigner une instance de @Id classe entité @GeneratedValue valeur générée private Long id; automatiquement – optionnel private String nom; Par défaut tous les attributs private String lieu; sont persistants R. Grin JPA page 7 R. Grin JPA page 8 7 8 Exemple d’entité – constructeurs Exemple d’entité – une association Un département - Autre bout de l’association plusieurs employés dans classe Employe public Departement() { } Obligatoire @OneToMany(mappedBy="dept") private List<Employe> employes = public Departement(String nom, new ArrayList<>(); Comment l’association sera String lieu) { traduite dans classe Employe ? this.nom = nom; public List<Employe> getEmployes() { this.lieu = lieu; return employes; } } public void addEmploye(Employe emp) { employes.add(emp); } R. Grin JPA page 9 R. Grin JPA page 10 9 10 Fichiers de configuration XML persistence.xml <persistence version= "2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"> META-INF/persistence.xml : informations <persistence-unit name="employes" 1 unité par BD sur les connexions aux BDs utilisées pour transaction-type="JTA"> conserver les entités <jta-data-source>java:app/jdbc/b1</jta-data-source> Contient le nom JNDI de la source de données <properties> nom JNDI dans le serveur d’application <property sur le serveur, mais pas les caractéristiques name="javax.persistence.schema-generation-action" de la BD, même pas son emplacement value="create"/> tables créées si n’existent pas Des informations plus techniques peuvent être <property name="eclipselink.logging.level" données par des propriétés, par exemple pour value="FINE"/> propriété non standard du fournisseur de dire si les ordres SQL générés par JPA sont </properties> persistance ; requêtes SQL générées par enregistrés dans les logs du serveur </persistence-unit> JPA enregistrées dans les logs du serveur </persistence> R. Grin JPA page 11 R. Grin JPA page 12 11 12 2 Définition d’une source de données Exemple 1Nom JNDI dans persistence.xml Soit directement dans le serveur d’application @DataSourceDefinition( (pas standardisé) name = "java:app/jdbc/b1", className = "com.mysql.cj.jdbc.MysqlDataSource", Soit dans l’application, portNumber = 3306, de façon standard serverName = "localhost", — par @DataSourceDefinition user = "root", password = "fflkq7dlfj", databaseName = "db1", Nom de la BD — dans un fichier de configuration standard properties= {"characterEncoding=UTF-8", dans le SGBD (web.xml par exemple) "useUnicode=true",…}) ou d’une façon particulière au serveur @Stateless Propriétés d’application (glassfish-resources.xml par public class MonEJB { ... } non standards exemple) R. Grin JPA page 13 R. Grin JPA page 14 13 14 Exemple 2 Gestionnaire d’entités (EM) <data-source> <description>Pour MySQL</description> Interface <name>java:app/jdbc/b1</name> javax.persistence.EntityManager <class-name>com.mysql.cj.jdbc.MysqlDataSource</class-name> <server-name>machin.unice.fr</server-name> Interlocuteur principal pour le développeur <port-number>3306</port-number> <database-name>testDB</database-name> Fournit les méthodes pour gérer les entités : <user>toto</user> les rendre persistantes <password>fs78jiia</password> Avantage par rapport à <property> @DataSourceDefinition : supprimer leurs valeurs dans la BD <name>useUnicode</name> le mot de passe peut être retrouver leurs valeurs dans la BD <value>true</value> modifié au déploiement </property> … ... <!– Autres propriétés --> </data-source> Pourquoi un avantage ? R. Grin JPA page 15 R. Grin JPA page 16 15 16 Contexte de persistance Exemple 1 nom dans persistence.xml ; em.persist(entité) @Stateless optionnel si une seule unité rend entité persistant sera géré par em public class DepartementFacade { Toute modification apportée à entité sera @PersistenceContext(unitName = "employes") enregistrée dans la BD par em au moment du private EntityManager em; EM injecté par le container commit public void create(Dept dept) { L’ensemble des entités gérées par un EM em.persist(dept); s’appelle un contexte de persistance (CP) dept.setLieu("Paris"); enregistré dans la BD ? } Transaction démarrée EM CP ... } au début de la méthode Pourquoi ? et fermée à la fin R. Grin JPA page 17 R. Grin JPA page 18 17 18 3 Exemple 2 Que fait cette méthode ? public void augmenter(String poste, int prime) { String requete = "SELECT e FROM Employe e " Pas du SQL, c’est du JPQL ; + " WHERE e.poste = :poste"; Employe est une classe Java Query query = em.createQuery(requete); query.setParameter("poste", poste); Entité List<Employe> liste = query.getResultList(); for (Employe e : liste) { e.setSalaire(e.getSalaire() + prime); } Est-ce que les augmentations } seront dans la base de données ? Oui, car les employés récupérés dans la BD sont ajoutés automatiquement par em dans le CP R. Grin JPA page 19 R. Grin JPA page 20 19 20 Conditions pour une classe entité Types d’accès à une valeur persistante Constructeur sans paramètre protected ou JPA peut accéder à la valeur d’un attribut de 2 public façons Attribut qui représente la clé primaire dans la BD par la variable d’instance ; accès « par champ » Pas final par les getters et setters ; Méthodes ou champs persistants pas final accès « par propriété » La classe ne doit pas nécessairement implémenter Serializable mais c’est requis dans certaines circonstances R. Grin JPA page 21 R. Grin JPA page 22 21 22 Exemple Quel type d’accès choisir ? Accès par champ : L’accès par propriété oblige à ajouter des getters @Id et des setters pour tous les attributs private int id; Choisir plutôt l’accès par champ Accès par propriété : @Id public int getId() { ... } Accès par champ ou par propriété, quelle est votre préférence ? R. Grin JPA page 23 R. Grin JPA page 24 23 24 4 Attributs persistants Cycle de vie d’une instance d’entité Par défaut, tous les attributs d’une entité sont L’instance peut être persistants nouvelle : créée mais pas gérée par un EM Exception : attribut avec un champ gérée par un EM (méthode persist, ou transient (mot-clé Java lié à la sérialisation) instance récupérée dans la BD) ou annoté par @Transient détachée : a une identité dans la BD mais n’est plus gérée par un EM supprimée : gérée par un EM ; données seront supprimées dans la BD au commit (méthode remove) R. Grin JPA page 25 R. Grin JPA page 26 25 26 Table de la base de données Exemple Dans les cas simples, une classe une table @Entity nom de la table = nom de la classe public class Departement { instances sauvegardées dans la table noms des colonnes = noms des attributs Departement (ou DEPARTEMENT) Par exemple, la classe Departement @Entity correspond à la table Departement avec les @Table(name = "DEPT") colonnes id, nom, lieu public class Departement { Convention plutôt que configuration pour JPA @Column pour changer le nom ou les attributs d’une colonne dans la table R. Grin JPA page 27 R. Grin JPA page 28 27 28 Types persistants Types « basic » Types primitifs (int, double,…) ou enveloppes Un attribut persistant peut être d’un des types de type primitifs (Integer,…) suivants : String, BigInteger, BigDecimal « basic » Types de l’API « time » Java 8 (LocalDate,…), « Embeddable » Date et Calendar (de java.util ; doivent être collection d’éléments de type « basic » ou annoté par @Temporal), Date, Time et Embeddable Timestamp (de java.sql ; peu utilisés) Énumérations Tableaux de byte, Byte, char, Character Plus généralement Serializable (sauvegardé comme un tout dans la base) R. Grin JPA page 29 R. Grin JPA page 30 29 30 5 Exemples Classe Embeddable private LocalDateTime dateOperationBancaire; Classe dont les données sont insérées dans // par défaut le numéro est enregistré dans la BD les lignes de la table d’une entité @Enumerated(EnumType.STRING) private TypeEmploye typeEmploye; R. Grin JPA page 31 R. Grin JPA page 32 31 32 Exemple Collection d’éléments @Embeddable public class Adresse { Pas besoin d’id Collection d’éléments de type basic ou private int numero; puisque les données embeddable