Les tables de hachage sont supportées par JPA, en tant que collections d'éléments (donc comme des collections de types de base), ou relations vers des entités. Chaque champ de type Map doit donc être annoté soit par @ElementCollection si les valeurs de cette table sont des types de base, soit par @OneToMany ou @ManyToMany si ce sont des entités.

La clé de cette table de hachage peut être un type de base. Dans ce cas, on peut annoter la Map avec @MapKeyColumn, ce qui permet de préciser les paramètres de la colonne qui portera cette clé, entre autres son nom. Si cette clé est une entité, alors une jointure sera utilisée pour retrouver cette entité. Dans ce cas, on peut préciser les paramètres de la colonne de jointure en utilisant l'annotation @MapKeyJoinColumn.

Enfin, les valeurs de cette table de hachage peuvent être des types de base. Dans ce cas, notre Map doit être annotée par @ElementCollection. S'il s'agit d'entités, alors l'annotation doit être @OneToMany ou @ManyToMany.

Ce cas est le cas nominal de JPA 1.0. La table de hachage que l'on gère est de type (type de base, entité), et la clé de chaque colonne correspond à un champ particulier de l'entité valeur.


Notre exemple comporte deux entités : Departement et Commune. L'entité Departement possède une table de hachage qui lui permet d'obtenir les objets commune à partir de leurs noms. Cette table est une relation @OneToMany, unidirectionnelle, qui créera donc une table de jointure.

L'annotation @MapKey sur cette table de hachage indique à JPA que c'est le champ name de l'entité valeur de cette table qui est utilisée comme clé. Ce champ n'est pas nécessairement la clé primaire de l'entité valeur (ici Commune), cela dit il vaut mieux qu'il y ait une contrainte d'unicité dessus.

La structure de table créée par JPA dans ce cas est la suivante. On remarque que la clé est stockée dans la table de jointure (colonne CommuneByName_Key). Si l'on avait choisi comme valeur la clé primaire de l'entité Commune, alors il n'y aurait pas eu besoin de cette colonne supplémentaire.


On remarque que ce schéma comporte une table de jointure, ce qui était prévu. Cette table de jointure porte deux colonnes : la première est une clé étrangère vers la clé primaire de Maire, l'autre vers la clé primaire de Departement. Nous sommes bien dans le cadre d'une relation 1:p unidirectionnelle avec table de jointure classique.

Une nouveauté de JPA 2.0 est le support de ce type de table. Pour construire un exemple nous avons besoin de trois entités : une qui porte la relation, une deuxième pour porter la clé de notre table, et une troisième qui porte la valeur. Construisons cet exemple.


Examinons à présent le schéma généré par JPA.


JPA a créé une table de jointure entre la table departement et la table commune. Ce point est attendu, dans la mesure où notre relation est définie entre deux entités associées à ces tables. La table de jointure définit deux clés étrangères, l'une vers commune, l'autre vers departement, ce qui est également le comportement nominal dans ce cas. Une colonne supplémentaire est créée, qui porte une clé étrangère vers la clé primaire de l'entité qui sert de clé à cette table, ici CommuneByMaire_Key. Ce mécanisme va permettre de récupérer des communes à partir de leur maire, comme on le souhaite dans cette relation.

JPA & EJB
Retour au blog Java le soir
Cours & Tutoriaux

Table des matières

Introduction
1. Objet du mapping objet / relationnel
2. Un peu d'histoire
Un premier exemple
1. Introduction
2. Création de l'environnement technique
2.1. Introduction
2.2. Création de la base Derby
2.3. Création du projet NetBeans et d'une première entité
2.4. Structure d'un projet persistant
2.5. Une première classe persistante
2.6. Un premier fichier persistence.xml
3. Utilisation de ce premier exemple
3.1. Écriture du code d'utilisation
3.2. Exécution de notre premier exemple
3.3. Modification de la class Marin
3.4. Opérations CRUD
Mettre un jeu de classes en base
1. Introduction
2. Définition d'une entité JPA
2.1. Écriture de l'entité
2.2. Annotation de l'entité
2.3. Annotations des champs
2.4. Exemple d'utilisation
3. Opérations sur les entités
3.1. Introduction
3.2. Opération PERSIST
3.3. Opération REMOVE
3.4. Opération REFRESH
3.5. Opération DETACH
3.6. Opération MERGE
4. Mise en relation d'entités
4.1. Introduction
4.2. Relations unidirectionnelles et bidirectionnelles
4.3. Relation 1:1
4.4. Relation 1:p
4.5. Relation p:1
4.6. Relation n:p
4.7. Comportement cascade
4.8. Effacement des entités orphelines
5. Charger des entités et leurs relations
6. Objets inclus
6.1. Introduction
6.2. Déclaration d'un objet inclus
6.3. Utilisation d'objets inclus
6.4. Cas où l'objet inclus est nul
6.5. Renommer les colonnes incluses
6.6. Collections d'objets inclus
L'API Collection en base
1. Introduction
2. Enregistrer une collection d'entités
2.1. Enregistrement d'une collection simple
2.2. Enregistrement d'un Set
2.3. Enregistrement d'une List
3. Enregistrer une collection de types de base
4. Enregistrement d'une Map
4.1. Table de hachage de type (type de base, entité)
4.2. Cas où la clé est un champ de la valeur
4.3. Cas d'une table (entité, entité)
Héritage
1. Introduction
2. Enregistrement d'une hiérarchie de classes
2.1. Entité et super-classe non enregistrée
2.2. Position du problème
2.3. Trois façons de faire
3. Stratégie SINGLE_TABLE
3.1. Fonctionnement
3.2. Mise en place
3.3. Limitations
4. Stratégie JOINED
4.1. Fonctionnement
4.2. Mise en place
4.3. Limitations
5. Stratégie TABLE_PER_CLASS
5.1. Fonctionnement
5.2. Mise en place
5.3. Limitations
Requêtes
1. Introduction
2. Un premier exemple
2.1. Écriture d'une première requête
2.2. Exécution d'une première requête
2.3. Exécution d'une première requête d'agrégation
3. Définition de requêtes
3.1. Requêtes dynamiques
3.2. Requêtes paramétrées
3.3. Requêtes nommées
3.4. Requêtes natives
4. Exécution, analyse du résultat
4.1. Exécution d'une requête dynamique
4.2. Exécution d'une requête nommée
4.3. Analyse du résultat
4.4. Cas des résultats de grande taille
4.5. Remarques
5. Clause From
5.1. Définition des entités
5.2. Jointures dans la clause From
5.3. Remarque finale sur les jointures en JPQL
6. Clause Where
6.1. Variables et chemins dans une clause where
6.2. Expressions conditionnelles et opérateurs
6.3. Requêtes imbriquées
6.4. Opérateurs any, all et some
6.5. Expressions fonctionnelles
7. Clauses Group By et Having
8. Opérations Update et Delete
EJB
1. Introduction
2. Un premier exemple
2.1. Introduction
2.2. Installation dans Glassfish à l'aide de Netbeans
2.3. Création d'un premier EJB
2.4. Déploiement de notre premier EJB
2.5. Création d'un client
3. Mise en oeuvre du pattern session facade
3.1. Introduction
3.2. Modèle objet
3.3. Définition de l'unité de persistance
3.4. Assemblage de notre application
3.5. Assemblage et déploiement
3.6. Utilisation du client
4. Opération de persistance en façade
4.1. Introduction
4.2. Enrichissement du service
4.3. Création de la méthode findMarinById(long)
4.4. Ajout de la méthode findAllMarins()
4.5. Utilisation dans un code client
5. Types d'EJB
5.1. Introduction
5.2. Qu'est-ce qu'un EJB ?
5.3. Écriture d'un EJB session
5.4. Qu'est-ce qu'une méthode métier ?
5.5. EJB avec ou sans état
5.6. Gestion des transactions
5.7. Restrictions
6. Cycle de vie d'un EJB
6.1. Cas des EJB sans état
6.2. Cas des EJB avec état
6.3. Injection de dépendances
7. Transaction gérée par l'EJB
7.1. Introduction
7.2. Déclaration du mode transactionnel
7.3. Gestion de la transaction
7.4. Fonctionnement de la transaction
7.5. Cas des EJB avec état
8. Transaction gérée par le serveur
8.1. Introduction
8.2. Déclaration du mode transactionnel
8.3. Gestion de la transaction
8.4. Fonctionnement de la transaction
8.5. Remarques
9. Intercepteurs
9.1. Introduction
9.2. Aperçu général
9.3. Cycle de vie d'un intercepteur
9.4. Object InvocationContext
9.5. Interception d'un EJB ou d'une méthode métier
9.6. Exemple de mise en œuvre d'un intercepteur