Outils pour utilisateurs

Outils du site


lang:java:jpa

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
lang:java:jpa [2017/09/09 19:38] – maff => mhtml rootlang:java:jpa [2020/05/11 00:31] (Version actuelle) – Suppression de la taille par défaut pour les images root
Ligne 2: Ligne 2:
  
 =====Cycle de vie===== =====Cycle de vie=====
-{{:lang:java:jpa:intro_02.png?954|Cycle de vie EJB}}+{{ :lang:java:jpa:cycle_de_vie_jpa.svg |}}
  
-[[https://armahdian.wordpress.com/2010/11/18/%D9%85%D8%B9%D8%B1%D9%81%DB%8C-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-java-ee-%D9%88-ejb-3/|معرفی معماری Java EE و EJB 3 _ آموزش برنامه نویسی]]{{ :lang:java:jpa:معرفی_معماری_java_ee_و_ejb_3_آموزش_برنامه_نویسی.mhtml |Archive}}+[[https://armahdian.wordpress.com/2010/11/18/%D9%85%D8%B9%D8%B1%D9%81%DB%8C-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-java-ee-%D9%88-ejb-3/|معرفی معماری Java EE و EJB 3 _ آموزش برنامه نویسی]] {{ :lang:java:jpa:معرفی_معماری_java_ee_و_ejb_3_آموزش_برنامه_نویسی_2020-04-26_8_29_44_pm_.html |Archive du 18/11/2010 le 26/04/2020}}
  
 =====persistence.xml===== =====persistence.xml=====
-<note>''Hibernate'' semble ne pas supporter si les champs ''persistence'' sont dans un ''namespace''. ''EclipseLink'' a l'air de le supporter mais c'est ''Eclipse'' qui alors semble mal le prendre.</note>+<WRAP center round info 60%> 
 +''Hibernate'' semble ne pas supporter si les champs ''persistence'' sont dans un ''namespace''. ''EclipseLink'' a l'air de le supporter mais c'est ''Eclipse'' qui alors semble mal le prendre. 
 +</WRAP> 
 ''exclude-unlisted-classes'' : exclut toutes les classes non explicitement ''@Entity''. ''exclude-unlisted-classes'' : exclut toutes les classes non explicitement ''@Entity''.
  
Ligne 91: Ligne 94:
 Certaines classes ont besoin d'implémenter l'interface ''Serializable''. Certaines classes ont besoin d'implémenter l'interface ''Serializable''.
  
-<blockquote>If an entity instance is to be passed by value as a detached object (e.g., through a remote interface), the entity class must implement the ''Serializable'' interface.<cite>JSR 338: Java TM Persistence API, Version 2.1 [[https://jcp.org/en/jsr/detail?id=338|Source]], {{ :lang:java:jpa:javapersistence2.1.pdf |Archive}}</cite></blockquote>+<blockquote>If an entity instance is to be passed by value as a detached object (e.g., through a remote interface), the entity class must implement the ''Serializable'' interface.<cite>[[https://jcp.org/en/jsr/detail?id=338|JSR 338: Java TM Persistence API, Version 2.1]], {{ :lang:java:jpa:javapersistence2.1.pdf |Archive}}</cite></blockquote>
  
 La classe ne doit pas être finale et doit avoir un constructeur sans argument explicitement écrit avec une visibilité publique ou protégée. La classe ne doit pas être finale et doit avoir un constructeur sans argument explicitement écrit avec une visibilité publique ou protégée.
Ligne 132: Ligne 135:
 </code> </code>
 Défini le nom de la table si elle est (ou doit être) différente du nom de la classe. Défini le nom de la table si elle est (ou doit être) différente du nom de la classe.
 +
 +Il est possible d'y ajouter des contraintes d'unicité à l'intérieur de la table :
 +<code java>
 +@Table(name="EMPLOYE",
 +       uniqueConstraints={
 +               @UniqueConstraint(columnNames={"nom", "prenom"})
 +       })
 +</code>
 +
 +===@Access===
 +Indique la manière dont l%%'%%''entity manager'' va lire et modifier les attributs : directement avec l'attribut (''AccessType.FIELD'') ou en passant par les getter/setter (''AccessType.PROPERTY'').
 +
  
 ===@Inheritance=== ===@Inheritance===
Ligne 165: Ligne 180:
 @Entity @Entity
 @Inheritance(strategy = InheritanceType.JOINED) @Inheritance(strategy = InheritanceType.JOINED)
 +@Table(name="Videos")
 public class Video implements Serializable { public class Video implements Serializable {
   @Id   @Id
Ligne 376: Ligne 392:
  
 ===@Id=== ===@Id===
-Indique la clé primaire de la classe. Si elle est mise au dessus d'un attribut, la lecture/écriture de tous les attributs de la classe se fera directement sur les attributs. Si elle est mise au dessus d'un getter/setter, la lecture/écriture de tous les attributs de la classe se fera par l'intermédiaire des getter/setter. Je n'ai pas trouvé où c'est indiqué précisément dans la PJA et apparemment, je ne suis pas le seul : [[https://forums.manning.com/posts/list/31713.page|Default access type]]{{ :lang:java:jpa:default_access_type.mhtml |Archive}}.+Indique la clé primaire de la classe. Si elle est mise au dessus d'un attribut, la lecture/écriture de tous les attributs de la classe se fera directement sur les attributs. Si elle est mise au dessus d'un getter/setter, la lecture/écriture de tous les attributs de la classe se fera par l'intermédiaire des getter/setter. Je n'ai pas trouvé où c'est indiqué précisément dans la PJA et apparemment, je ne suis pas le seul : [[https://stackoverflow.com/questions/18441222/issue-with-jpa-mapping-for-two-nested-embeddable|Issue with JPA mapping for two nested @Embeddable]] {{ :lang:java:jpa:hibernate_-_issue_with_jpa_mapping_for_two_nested_embeddable_-_stack_overflow_2020-04-26_8_53_29_pm_.html |Archive du 26/08/2013 le 26/04/2020}}.
  
 Il est conseillé de mettre le setter de ''@Id'' en ''private''. Il est conseillé de mettre le setter de ''@Id'' en ''private''.
Ligne 454: Ligne 470:
 ===@GeneratedValue=== ===@GeneratedValue===
 En complément à ''@Id'', il est possible d'indiquer que la génération de l'Id doit être automatique. En complément à ''@Id'', il est possible d'indiquer que la génération de l'Id doit être automatique.
-   * ''strategy = GenerationType.AUTO'' : le type de génération est laissé à la discrétion de l'implémentation de PJA.+   * ''strategy = GenerationType.AUTO'' : le type de génération est laissé à la discrétion de l'implémentation de PJA. Valeur par défaut.
    * ''strategy = GenerationType.IDENTITY'' : auto-incrémentation d'un numéro de façon traditionnelle.    * ''strategy = GenerationType.IDENTITY'' : auto-incrémentation d'un numéro de façon traditionnelle.
-   * ''strategy = GenerationType.SEQUENCE'' : si j'ai bien compris, l'intérêt est pour un accès concurrent à la base de données. Dès qu'une application génère un objet, il ne prend pas qu'une seule valeur mais en réserve une certaine quantité. Ainsi, l'application suivante pourra utiliser la plage de données suivante. L'intérêt est de permettre au SGBD d'optimiser les requêtes et ainsi permettre l'ajout différé des objets. Cela ne semble être compatible que Oracle et PostgreSQL [[http://www.thoughts-on-java.org/jpa-generate-primary-keys/|How to generate primary keys with JPA and Hibernate]]{{ :lang:java:jpa:how_to_generate_primary_keys_with_jpa_and_hibernate.mhtml |Archive}}. Dans les autres cas, cela passe par l'utilisation d'une table supplémentaire ''hibernate_sequence'' et l'ajout d'un élément nécessite alors une opération de lecture préalable dans cette table.+   * ''strategy = GenerationType.SEQUENCE'' : si j'ai bien compris, l'intérêt est pour un accès concurrent à la base de données. Dès qu'une application génère un objet, il ne prend pas qu'une seule valeur mais en réserve une certaine quantité. Ainsi, l'application suivante pourra utiliser la plage de données suivante. L'intérêt est de permettre au SGBD d'optimiser les requêtes et ainsi permettre l'ajout différé des objets. Cela ne semble être compatible que Oracle et PostgreSQL [[https://thoughts-on-java.org/jpa-generate-primary-keys/|How to generate primary keys with JPA and Hibernate]] {{ :lang:java:jpa:how_to_generate_primary_keys_with_jpa_and_hibernate_2020-04-26_9_01_29_pm_.html |Archive du 2016 le 26/04/2020}}. 
 +   * ''strategy = GenerationType.TABLE''Dans les autres cas, cela passe par l'utilisation d'une table supplémentaire ''hibernate_sequence'' et l'ajout d'un élément nécessite alors une opération de lecture préalable dans cette table.
 <code java> <code java>
 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_generator") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_generator")
Ligne 466: Ligne 483:
  
 ===@Column=== ===@Column===
-Permet de spécifier les caractéristiques de la colonne de la base de données.+Permet de spécifier les caractéristiques de la colonne de la base de données, uniquement pour des colonnes n'étant pas des jointures (pour ''@ManyToOne'' il faut utiliser ''@JoinColumn'').
  
 Seul, il ne sert à rien puisque de toute façon, tous les attributs / getter/setter sont automatiquement persistants. L'objectif est de pouvoir définir : Seul, il ne sert à rien puisque de toute façon, tous les attributs / getter/setter sont automatiquement persistants. L'objectif est de pouvoir définir :
-   ''name = %%"XXXX"%%'' : le nom de la colonne, +^Option^Description^Valeur par défaut^ 
-   * ''unique = true'' : si la colonne est composée de clés uniques, +|''name = %%"XXXX"%%''|Le nom de la colonne|Nom de la propriété ou de l'attribut.| 
-   * ''nullable = true'' : si les valeurs null sont acceptées, +|''unique = true''|Si la colonne est composée de clés uniques.|''false''| 
-   * ''length=32'' : nombre de caractères d'une colonne de type ''String'' uniquement.+|''nullable = true''|Si les valeurs null sont acceptées.|''true''| 
 +|''length = 32''|Nombre de caractères d'une colonne de type ''String'' uniquement.|255| 
 +|''insertable = true'' \\ ''updatable = true''|Autorise ou non les requêtes INSERT et UPDATE.|true|
    * etc…    * etc…
  
Ligne 636: Ligne 655:
 </file> </file>
  
-[[https://docs.oracle.com/cd/E16439_01/doc.1013/e13981/cmp30cfg001.htm|Source]]{{ :lang:java:jpa:configuring_a_jpa_entity_primary_key.htm.maff |Archive}}+[[https://docs.oracle.com/cd/E16439_01/doc.1013/e13981/cmp30cfg001.htm|Configuring a JPA Entity Primary Key]] {{ :lang:java:e13981.pdf |Archive du 07/2019 le 26/04/2020}}
  
 ===@Temporal=== ===@Temporal===
Ligne 650: Ligne 669:
  
 ====Association/mapping==== ====Association/mapping====
-[[http://blog.paumard.org/cours/jpa/chap03-entite-relation.html|Source]]{{ :lang:java:jpa:4._mise_en_relation_d_entites.html.maff |Archive}}+[[http://blog.paumard.org/cours/jpa/chap03-entite-relation.html|Mise en relation d'entités]] {{ :lang:java:jpa:4._mise_en_relation_d_entites_2020-04-26_9_15_26_pm_.html |Archive du 2012 le 26/04/2020}} 
 ===@OneToOne=== ===@OneToOne===
 Association entre deux instances lorsque l'instance A ne peut appartenir qu'à l'instance B et que l'instance B ne peut appartenir qu'à l'instance A. Par exemple une personne et sa carte d'identité ou encore une personne et son adresse principale. Association entre deux instances lorsque l'instance A ne peut appartenir qu'à l'instance B et que l'instance B ne peut appartenir qu'à l'instance A. Par exemple une personne et sa carte d'identité ou encore une personne et son adresse principale.
Ligne 659: Ligne 679:
  
 Si on souhaite connaître la personne depuis la carte d'identité, il faut ajouter un champ ''Personne'' dans ''CarteDIdentite'' et un mapping ''OneToOne'' avec comme paramètre ''mappedBy=XXX'' avec ''XXX'' le nom de l'attribut de type ''CarteDIdentite'' dans la classe ''Personne''. Si on souhaite connaître la personne depuis la carte d'identité, il faut ajouter un champ ''Personne'' dans ''CarteDIdentite'' et un mapping ''OneToOne'' avec comme paramètre ''mappedBy=XXX'' avec ''XXX'' le nom de l'attribut de type ''CarteDIdentite'' dans la classe ''Personne''.
 +
 +<WRAP center round alert 60%>
 +?? ''mappedBy='' vaut le nom de la colonne ou le nom de l'attribut ??
 +</WRAP>
  
 ===@OneToMany=== ===@OneToMany===
Ligne 880: Ligne 904:
  
 @Entity @Entity
-public class Film {+public class Film implements Serializable {
   @Id   @Id
   private Integer id;   private Integer id;
Ligne 924: Ligne 948:
 </file> </file>
  
-====Code====+====EntityManager====
 ===Initialisation de la connexion === ===Initialisation de la connexion ===
 Hibernate 5 : Hibernate 5 :
Ligne 939: Ligne 963:
  
 ===Insertion=== ===Insertion===
-Hibernate :+Définition de l'objet à ajouter :
 <code java> <code java>
 Pays monPays = new Pays(); Pays monPays = new Pays();
Ligne 945: Ligne 969:
 monPays.setNom("Islande"); monPays.setNom("Islande");
 monPays.setLangue("Islandais"); monPays.setLangue("Islandais");
 +</code>
 +Hibernate :
 +<code java>
 session.beginTransaction(); session.beginTransaction();
 session.save(monPays); session.save(monPays);
 session.getTransaction().commit(); session.getTransaction().commit();
 </code> </code>
- 
 EclipseLink : EclipseLink :
 <code java> <code java>
Ligne 957: Ligne 983:
 </code> </code>
   * ''persist'' enregistre ''entite'' dans la base de données et fait que les données de ''entite'' dans la base de données seront mises à jour si les attributs sont modifiés.   * ''persist'' enregistre ''entite'' dans la base de données et fait que les données de ''entite'' dans la base de données seront mises à jour si les attributs sont modifiés.
 +  * ''remove'' a pour effet de rendre une entité non persistante.
 +  * ''refresh'' a pour effet de synchroniser l’état de l’entité en mémoire avec ses valeurs présentes en base de données. Nécessaire pour synchroniser un objet après un ''merge''.
 +  * ''detach'' a pour effet de détacher l’entité considérée de l’entity manager qui la gère, et, dès lors, les valeurs qu’on pourra affecter à cette entité ne seront pas prises en compte au prochain commit. Une telle instance reste persistante, et pourra être ensuite, par exemple, attachée à un autre entity manager).
   * ''merge'' enregistre ''entite'' dans la base de données mais les données de ''entite'' dans la base de données ne seront PAS mises à jour si les attributs sont modifiés.   * ''merge'' enregistre ''entite'' dans la base de données mais les données de ''entite'' dans la base de données ne seront PAS mises à jour si les attributs sont modifiés.
 +
 +{{ :lang:java:jpa:entity_manager.svg |}}
 +
 +===Gestion des flux===
 +  * ''close()'' : exécute toutes les requêtes SQL en attente puis ferme la connexion avec la base de données.
 +  * ''clear()'' : annule toutes les requêtes SQL en attente.
 +  * ''flush()'' : exécute toutes les requêtes SQL en attente.
  
 ===Lecture=== ===Lecture===
Ligne 972: Ligne 1008:
 </code> </code>
  
-  * HQL+<code java> 
 +List results = session.createCriteria(Item.class) 
 +  .add(Expression.eq("item.seller", user)) 
 +  .setFetchMode("bids", FetchMode.EAGER).list(); 
 +Iterator items = new HashSet(results).iterator(); 
 +while (items.hasNext()) 
 +
 +  ... 
 +
 +</code> 
 + 
 +Trouve en fonction de la clé primaire. 
 +<code java> 
 +Employe employe = em.find(Employe.class, 5233); 
 +</code> 
 +  * HQL / JPQL 
 + 
 +Le ''HQL'' est la version spécifique du ''JPQL'' pour ''Hibernate''
 Version simple Version simple
 <code java> <code java>
Ligne 987: Ligne 1041:
 List<Pays> resultat = query.getResultList(); List<Pays> resultat = query.getResultList();
 </code> </code>
 +
 +On notera ici la présence de '':code'' et la définition de sa valeur par ''query.setString("code", FR)''.
  
 Passer par des ''query'' avec des ''select'' permet d'éviter que le cache de premier niveau de ''Hibernate'' ne soit remplit. Passer par des ''query'' avec des ''select'' permet d'éviter que le cache de premier niveau de ''Hibernate'' ne soit remplit.
Ligne 1001: Ligne 1057:
 </code> </code>
  
-Et des jointures plus ou moins implicites pour des relations @ManyToOne et @OneToOne.+Exemple plus complet : 
 +<code sql> 
 +select employe 
 +  from Employe employe 
 +  where prenom = 'Pierre' 
 +</code> 
 +On constate que ''from'' est une classe, pas une table. ''select'' renvoie des instances, pas des colonnes. 
 + 
 +JPQL s'occupe de faire les jointures automatiques (''deptAffectation'' est une liaison ''ManyToOne'') : 
 +<code sql> 
 +select employe.deptAffectation 
 +  from Employe employe 
 +  where employe.prenom = 'Pierre' 
 +</code> 
 +est identique à 
 +<code sql> 
 +select departement 
 +  from Employe employe join employe.deptAffectation departement 
 +  where employe.prenom = 'Pierre' 
 +</code> 
 + 
 +On peut aussi forcer le préchargement (''fetch'') des données des tables jointes. 
 +<code sql> 
 +select employe 
 +  from Employe employe left join fetch employe.deptAffectation 
 +  where prenom = 'Pierre' 
 +</code> 
 + 
 + 
 +<WRAP center round important 60%> 
 +Ci-dessous, c'est le bordel... 
 +</WRAP> 
 + 
 +Et des jointures plus ou moins implicites pour des relations ''@ManyToOne'' et ''@OneToOne''.
 <code sql> <code sql>
 select titre from Film f where f.realisateur.nom = 'Eastwood' select titre from Film f where f.realisateur.nom = 'Eastwood'
Ligne 1040: Ligne 1129:
 </code> </code>
  
-Il n'est pas possible de faire une recherches directement dans une liaison @ManyToMany ou @ManyToOne. Dans ces cas, il faut passer par une jointure.+Il n'est pas possible de faire une recherche directement dans une liaison ''@ManyToMany'' ou ''@ManyToOne''. Dans ces cas, il faut passer par une jointure.
 <code sql> <code sql>
 select distinct film.titre from Film as film select distinct film.titre from Film as film
Ligne 1235: Ligne 1324:
 <code java> <code java>
 @Entity @Entity
-@NamedNativeQueries(value = {  +@NamedQueries(value = {  
-  @NamedNativeQuery+  @NamedQuery
   (   (
     resultClass=Commande.class,     resultClass=Commande.class,
-    name  = "TousLesPays", +    name  = "Pays.TousLesPays", 
     query = "select p from Pays p"     query = "select p from Pays p"
   )   )
 }) })
- 
 public class Pays implements Serializable { public class Pays implements Serializable {
  
Ligne 1250: Ligne 1338:
 List<Pays> list = em.createNamedQuery("TousLesPays", Pays.class).getResultList(); List<Pays> list = em.createNamedQuery("TousLesPays", Pays.class).getResultList();
 </code> </code>
-Lors qu'une classe ne possèque qu'une seule requête nommée, ''@NamedNativeQuery'' est suffisant. Sinon, il faut les ranger dans le paramètre ''value'' de ''@NamedNativeQueries'' sous forme d'un tableau.+Lors qu'une classe ne possèque qu'une seule requête nommée, ''@NamedQuery'' est suffisant. Sinon, il faut les ranger dans le paramètre ''value'' de ''@NamedQueries'' sous forme d'un tableau
 + 
 +Il n'est pas obligatoire que le nom soit ''NomClasse.nomQuery'' mais cela permet de bien ranger les ''Query''.
  
 ====hibernate.cfg.xml==== ====hibernate.cfg.xml====
lang/java/jpa.1504978728.txt.gz · Dernière modification : 2017/09/09 19:38 de root