Qu’est-ce que JPA ? Introduction à l’API de persistance Java

En tant que spécification, l’API de persistance Java concerne la persistance, ce qui signifie vaguement tout mécanisme par lequel les objets Java survivent au processus d’application qui les a créés. Tous les objets Java n’ont pas besoin d’être conservés, mais la plupart des applications conservent les objets métier clés. La spécification JPA vous permet de définir quels objets doivent être conservés et comment ces objets doivent être conservés dans vos applications Java.

En soi, JPA n’est pas un outil ou un framework; il définit plutôt un ensemble de concepts qui peuvent être mis en œuvre par n’importe quel outil ou cadre. Alors que le modèle ORM (object-relational mapping) de JPA était à l’origine basé sur Hibernate, il a depuis évolué. De même, alors que JPA était initialement destiné à être utilisé avec des bases de données relationnelles / SQL, certaines implémentations JPA ont été étendues pour une utilisation avec les banques de données NoSQL. EclipseLink, l’implémentation de référence de JPA 2.2, est un framework populaire qui prend en charge JPA avec NoSQL.

JPA et Hibernate

En raison de leur histoire entrelacée, Hibernate et JPA sont fréquemment confondus. Cependant, comme la spécification de servlet Java, JPA a engendré de nombreux outils et frameworks compatibles ; Hibernate n’en est qu’un.

Développé par Gavin King et publié début 2002, Hibernate est une bibliothèque ORM pour Java. King a développé Hibernate comme alternative aux haricots d’entité pour la persistance. Le cadre était si populaire, et si nécessaire à l’époque, que beaucoup de ses idées ont été adoptées et codifiées dans la première spécification JPA.

Aujourd’hui, Hibernate ORM est l’une des implémentations JPA les plus matures, et reste une option populaire pour ORM en Java. Hiberner ORM 5.3.8 (la version actuelle au moment d’écrire ces lignes) implémente JPA 2.2. De plus, la famille d’outils d’Hibernate s’est élargie pour inclure des outils populaires tels que la recherche Hibernate, le validateur Hibernate et l’OGM Hibernate, qui prend en charge la persistance du modèle de domaine pour NoSQL.

Qu’est-ce que Java ORM ?

Bien qu’elles diffèrent par leur exécution, chaque implémentation JPA fournit une sorte de couche ORM. Afin de comprendre JPA et les outils compatibles JPA, vous devez avoir une bonne compréhension de l’ORM.

Le mappage objet-relationnel est une tâche que les développeurs ont de bonnes raisons d’éviter de faire manuellement. Un framework comme Hibernate ORM ou EclipseLink codifie cette tâche en une bibliothèque ou un framework, une couche ORM. Dans le cadre de l’architecture d’application, la couche ORM est responsable de la gestion de la conversion des objets logiciels pour interagir avec les tables et les colonnes d’une base de données relationnelle. En Java, la couche ORM convertit les classes et objets Java afin qu’ils puissent être stockés et gérés dans une base de données relationnelle.

Par défaut, le nom de l’objet persistant devient le nom de la table et les champs deviennent des colonnes. Une fois la table configurée, chaque ligne de table correspond à un objet dans l’application. Le mappage d’objets est configurable, mais les valeurs par défaut ont tendance à bien fonctionner.

La figure 1 illustre le rôle de JPA et de la couche ORM dans le développement d’applications.

JavaWorld/IDG

Figure 1. JPA et la couche ORM

Configuration de la couche ORM Java

Lorsque vous configurez un nouveau projet pour utiliser JPA, vous devez configurer la banque de données et le fournisseur JPA. Vous configurerez un connecteur de banque de données pour vous connecter à la base de données de votre choix (SQL ou NoSQL). Vous allez également inclure et configurer le fournisseur JPA, qui est un framework tel que Hibernate ou EclipseLink. Bien que vous puissiez configurer JPA manuellement, de nombreux développeurs choisissent d’utiliser le support prêt à l’emploi de Spring. Voir « Installation et configuration JPA » ci-dessous pour une démonstration de l’installation et de la configuration JPA manuelles et à ressorts.

Persistance des données en Java

Du point de vue de la programmation, la couche ORM est une couche d’adaptateur: il adapte le langage des graphes objets au langage des tables SQL et relationnelles. La couche ORM permet aux développeurs orientés objet de créer des logiciels qui conservent les données sans jamais quitter le paradigme orienté objet.

Lorsque vous utilisez JPA, vous créez une carte de la banque de données vers les objets de modèle de données de votre application. Au lieu de définir comment les objets sont enregistrés et récupérés, vous définissez le mappage entre les objets et votre base de données, puis appelez JPA pour les conserver. Si vous utilisez une base de données relationnelle, une grande partie de la connexion réelle entre le code de votre application et la base de données sera alors gérée par JDBC, l’API de connectivité de base de données Java.

En tant que spécification, JPA fournit des annotations de métadonnées, que vous utilisez pour définir le mappage entre les objets et la base de données. Chaque implémentation JPA fournit son propre moteur pour les annotations JPA. La spécification JPA fournit également les PersistanceManager ou EntityManager, qui sont les points de contact clés avec le système JPA (dans lequel votre code logique métier indique au système quoi faire avec les objets mappés).

Pour rendre tout cela plus concret, envisagez la liste 1, qui est une classe de données simple pour modéliser un musicien.

Liste 1. Une classe de données simple en Java

La classe Musician de la liste 1 est utilisée pour contenir des données. Il peut contenir des données primitives telles que le champ nom. Il peut également contenir des relations avec d’autres classes telles que mainInstrument et performances.La raison d’être de

Musician est de contenir des données. Ce type de classe est parfois appelé DTO ou objet de transfert de données. Les DTO sont une caractéristique commune du développement de logiciels. Bien qu’ils contiennent de nombreux types de données, ils ne contiennent aucune logique métier. La persistance d’objets de données est un défi omniprésent dans le développement de logiciels.

Persistance des données avec JDBC

Une façon d’enregistrer une instance de la classe Musician dans une base de données relationnelle serait d’utiliser la bibliothèque JDBC. JDBC est une couche d’abstraction qui permet à une application d’émettre des commandes SQL sans penser à l’implémentation de la base de données sous-jacente.

La liste 2 montre comment vous pouvez conserver la classe Musician en utilisant JDBC.

Liste 2. JDBC insérant un enregistrement

Le code de la liste 2 est assez auto-documenté. L’objet georgeHarrison peut provenir de n’importe où (soumission frontale, service externe, etc.), et a ses champs ID et nom définis. Les champs de l’objet sont ensuite utilisés pour fournir les valeurs d’une instruction SQL insert. (La classe PreparedStatement fait partie de JDBC, offrant un moyen d’appliquer des valeurs en toute sécurité à une requête SQL.)

Alors que JDBC permet le contrôle fourni avec la configuration manuelle, il est lourd par rapport à JPA. Afin de modifier la base de données, vous devez d’abord créer une requête SQL qui mappe de votre objet Java aux tables d’une base de données relationnelle. Vous devez ensuite modifier le SQL chaque fois qu’une signature d’objet change. Avec JDBC, la maintenance du SQL devient une tâche en soi.

Persistance des données avec JPA

Considérons maintenant la liste 3, où nous persistons la classe Musician en utilisant JPA.

Liste 3. La persistance de George Harrison avec JPA

Musician georgeHarrison = new Musician(0, "George Harrison");musicianManager.save(georgeHarrison);

La liste 3 remplace le SQL manuel de la liste 2 par une seule ligne, session.save(), qui demande à JPA de conserver l’objet. À partir de ce moment, la conversion SQL est gérée par le framework, vous n’avez donc plus besoin de quitter le paradigme orienté objet.

Annotations de métadonnées dans JPA

La magie de la liste 3 est le résultat d’une configuration créée à l’aide des annotations de JPA. Les développeurs utilisent des annotations pour indiquer à JPA quels objets doivent être conservés et comment ils doivent être conservés.

La liste 4 affiche la classe Musician avec une seule annotation JPA.

Liste 4. L’annotation @Entity de JPA

@Entitypublic class Musician { // ..class body}

Les objets persistants sont parfois appelés entités. Attacher @Entity à une classe comme Musician informe JPA que cette classe et ses objets doivent être conservés.

Configuration de JPA

Comme la plupart des frameworks modernes, JPA adopte le codage par convention (également connu sous le nom de convention over configuration), dans lequel le framework fournit une configuration par défaut basée sur les meilleures pratiques du secteur. Par exemple, une classe nommée Musician serait mappée par défaut à une table de base de données appelée Musician.

La configuration conventionnelle est un gain de temps, et dans de nombreux cas, elle fonctionne assez bien. Il est également possible de personnaliser votre configuration JPA. Par exemple, vous pouvez utiliser l’annotation @Table de JPA pour spécifier la table où la classe Musician doit être stockée.

Liste 5. L’annotation @Table de JPA

@Entity@Table(name="musician")public class Musician { // ..class body}

La liste 5 indique à JPA de conserver l’entité (classe Musician) dans la table musician.

Clé primaire

Dans JPA, la clé primaire est le champ utilisé pour identifier de manière unique chaque objet de la base de données. La clé primaire est utile pour référencer et relier des objets à d’autres entités. Chaque fois que vous stockez un objet dans une table, vous spécifiez également le champ à utiliser comme clé primaire.

Dans la liste 6, nous indiquons à JPA quel champ utiliser comme clé primaire de Musician.

Liste 6. Spécification de la clé primaire

@Entitypublic class Musician { @Id private Long id;

Dans ce cas, nous avons utilisé l’annotation @Id de JPA pour spécifier le champ id comme clé primaire de Musician. Par défaut, cette configuration suppose que la clé primaire sera définie par la base de données – par exemple, lorsque le champ est défini sur l’incrémentation automatique sur la table.

JPA prend en charge d’autres stratégies pour générer la clé primaire d’un objet. Il a également des annotations pour changer les noms de champs individuels. En général, JPA est suffisamment flexible pour s’adapter à tout mappage de persistance dont vous pourriez avoir besoin.

Opérations CRUD

Une fois que vous avez mappé une classe sur une table de base de données et établi sa clé primaire, vous avez tout ce dont vous avez besoin pour créer, récupérer, supprimer et mettre à jour cette classe dans la base de données. L’appel de session.save() créera ou mettra à jour la classe spécifiée, selon que le champ de clé primaire est null ou s’applique à une entité existante. L’appel de entityManager.remove() supprimera la classe spécifiée.

Relations d’entités dans JPA

La simple persistance d’un objet avec un champ primitif n’est que la moitié de l’équation. JPA a également la capacité de gérer des entités les unes par rapport aux autres. Quatre types de relations d’entités sont possibles dans les tables et les objets:

    1. Un à plusieurs
    2. Plusieurs à un
    3. Plusieurs à plusieurs
    4. Un à un

Chaque type de relation décrit la relation entre une entité et d’autres entités. Par exemple, l’entité Musician peut avoir une relation un-à-plusieurs avec Performance, une entité représentée par une collection telle que List ou Set.

Si le champ Musician incluait un champ Band, la relation entre ces entités pourrait être plusieurs à un, ce qui implique une collection de Musicians sur le seul Band classe. (En supposant que chaque musicien ne joue que dans un seul groupe.)

Si Musicianincluait un champ BandMates, cela pourrait représenter une relation plusieurs à plusieurs avec d’autres entités Musician.

Enfin, Musician peut avoir une relation un à un avec une entité Quote, utilisée pour représenter une citation célèbre : Quote famousQuote = new Quote().

Définition des types de relations

JPA a des annotations pour chacun de ses types de mappage de relations. La liste 7 montre comment vous pouvez annoter la relation un à plusieurs entre Musician et Performances.

Liste 7. Annotation d’une relation un-à-plusieurs

Une chose à remarquer est que @JoinColumn indique à JPA quelle colonne de la table de performances correspondra à l’entité Musician. Chaque performance sera associée à un seul Musician, qui est suivi par cette colonne. Lorsque JPA charge un Musician ou un Performance dans la base de données, il utilisera ces informations pour reconstituer le graphique d’objets.

Stratégies de récupération dans JPA

En plus de savoir où placer les entités associées dans la base de données, JPA doit savoir comment vous souhaitez les charger. Les stratégies de récupération indiquent à JPA comment charger des entités associées. Lors du chargement et de l’enregistrement d’objets, un framework JPA doit permettre d’affiner la gestion des graphiques d’objets. Par exemple, si la classe Musician a un champ bandMate (comme indiqué dans la liste 7), le chargement de george peut entraîner le chargement de la table Musician entière à partir de la base de données!

Ce qui est nécessaire, c’est la capacité de définir le chargement paresseux des entités liéesrecognizing reconnaissant, bien sûr, que les relations dans JPA peuvent être impatientes ou paresseuses. Vous pouvez utiliser des annotations pour personnaliser vos stratégies de récupération, mais la configuration par défaut de JPA fonctionne souvent prête à l’emploi, sans modifications :

  1. One-to-many:Lazy
  2. Many-to-one: Eager
  3. Many-to-many:Lazy
  4. One-to-one:Eager

Installation et configuration de JPA

Nous conclurons par un rapide coup d’œil sur l’installation et la configuration de JPA pour vos applications Java. Pour cette démonstration, j’utiliserai EclipseLink, l’implémentation de référence JPA.

La manière courante d’installer JPA consiste à inclure un fournisseur JPA dans votre projet. La liste 8 montre comment inclure EclipseLink en tant que dépendance dans votre fichier Maven pom.xml.

Liste 8. Incluez EclipseLink en tant que dépendance Maven

org.eclipse.persistenceeclipselink2.5.0-RC1

Vous devrez également inclure le pilote de votre base de données, comme indiqué dans la liste 9.

Liste 9. Dépendance Maven pour un connecteur MySQL

mysqlmysql-connector-java5.1.32

Ensuite, vous devrez informer le système de votre base de données et de votre fournisseur. Cela se fait dans le fichier persistence.xml, comme indiqué dans la liste 10.

Liste 10. Persistance.xml

Il existe d’autres moyens de fournir ces informations au système, y compris par programmation. Je recommande d’utiliser le fichier persistence.xml car le stockage des dépendances de cette façon facilite la mise à jour de votre application sans modifier le code.

Configuration Spring pour JPA

L’utilisation de Spring facilitera grandement l’intégration de JPA dans votre application. Par exemple, placer l’annotation @SpringBootApplication dans l’en-tête de votre application demande à Spring de rechercher automatiquement les classes et d’injecter le EntityManager selon les besoins, en fonction de la configuration que vous avez spécifiée.

La liste 11 affiche les dépendances à inclure si vous souhaitez prendre en charge JPA de Spring pour votre application.

Liste 11. Ajout du support JPA Spring dans Maven

Conclusion

Chaque application qui traite une base de données doit définir une couche d’application dont le seul but est d’isoler le code de persistance. Comme vous l’avez vu dans cet article, l’API de persistance Java introduit une gamme de fonctionnalités et de prise en charge de la persistance des objets Java. Les applications simples peuvent ne pas nécessiter toutes les capacités de JPA et, dans certains cas, la surcharge liée à la configuration du framework peut ne pas être justifiée. À mesure qu’une application se développe, cependant, la structure et l’encapsulation de JPA gagnent vraiment leur vie. L’utilisation de JPA simplifie votre code objet et fournit un cadre conventionnel pour accéder aux données dans les applications Java.

En savoir plus sur l’API de persistance Java et les technologies associées

  • Qu’est-ce que JDBC ? Introduction à la connectivité des bases de données Java : Découvrez l’API de bas niveau de Java pour vous connecter à une base de données, émettre des requêtes SQL, etc.
  • Persistance Java avec JPA et Hibernate, Partie 1: Entités et relations: Commencez à modéliser des entités et des relations avec Java 8 et Hibernate ORM.
  • Persistance Java avec JPA et Hibernate, partie 2: Pratique pratique de la modélisation de relations multiples et de relations d’héritage dans Java 8 et Hibernate ORM.
  • Implémentation d’un comportement dépendant de l’état : Une introduction classique au modèle d’état et à la dépendance d’état en Java.
  • Chargement Impatient / paresseux en Hibernate: Comment appliquer un chargement impatient et paresseux en Hibernate.
  • JPA 2.2 apporte quelques changements très attendus : Un aperçu des mises à jour des spécifications dans JPA 2.2, y compris des améliorations du CDI, un meilleur alignement avec l’API Date et Heure et la prise en charge des annotations @Repeatable.
  • Devriez-vous utiliser JPA pour votre prochain projet?: Questions clés qui pourraient vous aider à décider.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *