Les deux principales annotations que l'on peut mettre sur la déclaration d'une classe sont @Entity, @Table et @Access. Il existe d'autres annotations que nous verrons lorsque nous traiterons l'héritage.

L'annotation @Entity nous indique que cette classe est une classe persistante. Elle peut prendre un attribut name, qui fixe le nom de cette entité. Par défaut, le nom d'une entité est le nom complet de sa classe. On peut fixer le nom d'une entité par une constante, en utilisant un import statique.

L'annotation @Table permet de fixer le nom de la table dans laquelle les instances de cette classe vont être écrites. Cette annotation est particulièrement utile lorsque l'on doit associer un jeu de classes à des tables existantes. L'annotation @Table supporte plusieurs attributs :

  • Les attributs catalog, schema et name : permettent de fixer les paramètres de la table utilisée.

  • L'attribut @UniqueConstraints permet d'écrire des contraintes d'unicité sur des colonnes ou des groupes de colonnes.

Enfin, l'annotation @Access permet de fixer la façon dont l'entity manager va lire et écrire les valeurs des champs de cette classe. Cette annotation ne prend qu'un seul attribut, qui ne peut prendre que deux valeurs : AccessType.FIELD et AccessType.PROPERTY. Dans le premier cas, les lectures / modifications se font directement sur les champs, dans le second elles passent par les getters / setters . Notons que cette annotation peut aussi être placée sur les champs ou getters d'une classe. On peut donc particulariser l'injection de valeur champ par champ.

Voyons ceci sur un exemple de classe Marin.


Notons que l'on peut mettre autant de contraintes @UniqueConstraint que l'on veut, séparées par des virgules.

Dans notre exemple, le nom de l'entité est fixée par une constante, importée statiquement. La table dans laquelle les instance de cette classe seront écrites se nomme marin. Nous avons écrit une contrainte d'unicité, nommée nom_prenom, qui impose de ne pas avoir deux marins qui portent même nom et même prénom.

Enfin, nous avons annoté notre entité de sorte que les lecture / écriture des valeurs de ses champs se fassent par injection directe sur les champs.

D'une façon générale, les champs d'une classe sont automatiquement associés à des colonnes en base, dans la table de l'entité. De plus, ces colonnes portent les mêmes noms que ces champs. Si cette règle par défaut suffit, alors il n'y a pas à annoter les champs.

Les types associés automatiquement à des colonnes sont les suivants :

  • Tous les types de base Java : int, long, float, etc...

  • Tous les types enveloppes ( wrappers ) des types de base, et le type String.

  • Les types date java.sql.Date, java.sql.Time et java.sql.TimeStamp. Les types java.util.Date et java.util.Calendar ne sont donc pas associés automatiquement.

  • Les types énumérés.

  • Les types Serializable, qui sont rangés dans des blob .

Il arrive très fréquemment que l'on doive particulariser le type d'application entre un champ d'une classe et une colonne d'une table. Il est notamment très fréquent que le nom choisi par défaut ne convienne pas, on doit donc le fixer à la main.

On dispose pour cela de deux annotations : @Column et @Lob. Le cas de l'annotation @Basic, qui s'applique aux champs sera traité dans la suite.

Voyons tout ceci sur un exemple.


On notera plusieurs choses sur cet exemple :

  • La contrainte @UniqueConstraint référence bien les noms des colonnes et non pas les noms des champs. Si l'on change les noms des colonnes dans les annotations @Column, alors ils doivent être propagés dans cette contrainte.

  • Les tailles des champs nom et prenom en base sont limités à 50 caractères. Cette limite ne s'applique qu'à la base, ce qui entraînera une troncature du champ s'il est trop long.

  • Le champ age est automatiquement associé à une colonne age dans la table marin.

  • Nous avons choisi d'associer notre champ civilite à une colonne de type chaîne de caractères. Cela rendra le contenu de notre table plus lisible, mais surtout indépendant de l'énumération Civility. Choisir d'écrire en base les numéros d'ordre des éléments énumérés impose effectivement de ne jamais changer ces numéros d'ordre. Cette contrainte, impossible à réaliser dans la pratique, ne se pose pas dans notre cas.

  • On notera enfin l'association manuelle de java.util.Date avec TemporalType.DATE.

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