Vlad Mihalcea

Dernière modification:

Imaginez avoir un outil capable de détecter automatiquement les problèmes de performances JPA et de mise en veille prolongée. L’optimiseur d’hypersistance est cet outil!

Introduction

Si vous vous demandez pourquoi et quand vous devriez utiliser JPA ou Hibernate, cet article va vous fournir une réponse à cette question très courante. Parce que j’ai vu cette question posée très souvent sur le canal / r / java Reddit, j’ai décidé qu’il valait la peine d’écrire une réponse approfondie sur les forces et les faiblesses de JPA et Hibernate.

Bien que JPA soit un standard depuis sa sortie en 2006, ce n’est pas la seule façon d’implémenter une couche d’accès aux données en utilisant Java. Nous allons discuter des avantages et des inconvénients de l’utilisation de JPA ou de toute autre alternative populaire.

Pourquoi et quand JDBC a été créé

En 1997, Java 1.1 a introduit l’API JDBC (Java Database Connectivity), très révolutionnaire pour l’époque puisqu’elle offrait la possibilité d’écrire la couche d’accès aux données une fois à l’aide d’un ensemble d’interfaces et de l’exécuter sur n’importe quelle base de données relationnelle implémentant l’API JDBC sans avoir à modifier le code de votre application.

L’API JDBC offrait une interface Connection pour contrôler les limites des transactions et créer des instructions SQL simples via l’API Statement ou des instructions préparées qui vous permettent de lier des valeurs de paramètres via l’API PreparedStatement.

Donc, en supposant que nous ayons une table de base de données post et que nous voulons insérer 100 lignes, voici comment nous pourrions atteindre cet objectif avec JDBC:

int postCount = 100;int batchSize = 50;try (PreparedStatement postStatement = connection.prepareStatement(""" INSERT INTO post ( id, title ) VALUES ( ?, ? ) """)) { for (int i = 1; i <= postCount; i++) { if (i % batchSize == 0) { postStatement.executeBatch(); } int index = 0; postStatement.setLong( ++index, i ); postStatement.setString( ++index, String.format( "High-Performance Java Persistence, review no. %1$d", i ) ); postStatement.addBatch(); } postStatement.executeBatch();} catch (SQLException e) { fail(e.getMessage());}

Bien que nous ayons profité des blocs de texte multi-lignes et des blocs d’essai avec des ressources pour éliminer l’appel PreparedStatement close, l’implémentation est toujours très verbeuse. Notez que les paramètres de liaison commencent à partir de 1, pas 0 comme vous pouvez en avoir l’habitude avec d’autres API bien connues.

Pour récupérer les 10 premières lignes, nous pourrions avoir besoin d’exécuter une requête SQL via le PreparedStatement, qui renverra un ResultSet représentant le résultat de la requête basée sur une table. Cependant, étant donné que les applications utilisent des structures hiérarchiques, comme JSON ou DTO pour représenter les associations parent-enfant, la plupart des applications devaient transformer le JDBC ResultSet dans un format différent dans la couche d’accès aux données, comme illustré par l’exemple suivant:

int maxResults = 10;List<Post> posts = new ArrayList<>();try (PreparedStatement preparedStatement = connection.prepareStatement(""" SELECT p.id AS id, p.title AS title FROM post p ORDER BY p.id LIMIT ? """)) { preparedStatement.setInt(1, maxResults); try (ResultSet resultSet = preparedStatement.executeQuery()) { while (resultSet.next()) { int index = 0; posts.add( new Post() .setId(resultSet.getLong(++index)) .setTitle(resultSet.getString(++index)) ); } }} catch (SQLException e) { fail(e.getMessage());}

Encore une fois, c’est la meilleure façon d’écrire cela avec JDBC car nous utilisons des blocs de texte, des essais avec des ressources et une API de style fluide pour créer les objets Post.

Néanmoins, l’API JDBC est toujours très détaillée et, plus important encore, manque de nombreuses fonctionnalités requises lors de la mise en œuvre d’une couche d’accès aux données moderne, comme:

  • Un moyen de récupérer des objets directement à partir du jeu de résultats de la requête. Comme nous l’avons vu dans l’exemple ci-dessus, nous devons itérer ReusltSet et extraire les valeurs de colonne pour définir les propriétés de l’objet Post.
  • Un moyen transparent d’obtenir des instructions par lots sans avoir à réécrire le code d’accès aux données lors du passage du mode par défaut sans traitement par lots à l’utilisation du traitement par lots.
  • prise en charge du verrouillage optimiste
  • Une API de pagination qui masque la syntaxe de requête Top-N et Next-N spécifique à la base de données sous-jacente

Pourquoi et quand Hibernate a été créé

En 1999, Sun a publié J2EE (Java Enterprise Edition), qui offrait une alternative à JDBC, appelée Beans d’entité.

Cependant, comme les Beans d’entités étaient notoirement lents, trop compliqués et encombrants à utiliser, en 2001, Gavin King a décidé de créer un framework ORM capable de mapper des tables de base de données sur des POJOs (Objets Java simples), et c’est ainsi qu’Hibernate est né.

Étant plus léger que les Beans d’entités et moins verbeux que JDBC, Hibernate est devenu de plus en plus populaire, et il est rapidement devenu le framework de persistance Java le plus populaire, gagnant JDO, iBatis, Oracle TopLink et Apache Cayenne.

Pourquoi et quand JPA a-t-il été créé ?

Tirant les leçons du succès du projet Hibernate, la plate-forme Java EE a décidé de standardiser la façon dont Hibernate et Oracle TopLink, et c’est ainsi que JPA (Java Persistence API) est né.

JPA n’est qu’une spécification et ne peut pas être utilisée seule, ne fournissant qu’un ensemble d’interfaces qui définissent l’API de persistance standard, qui est implémentée par un fournisseur JPA, comme Hibernate, EclipseLink ou OpenJPA.

Lorsque vous utilisez JPA, vous devez définir le mappage entre une table de base de données et son objet entité Java associé:

@Entity@Table(name = "post")public class Post { @Id private Long id; private String title; public Long getId() { return id; } public Post setId(Long id) { this.id = id; return this; } public String getTitle() { return title; } public Post setTitle(String title) { this.title = title; return this; }}

Par la suite, nous pouvons réécrire l’exemple précédent qui a enregistré 100 enregistrements post ressemble à ceci:

for (long i = 1; i <= postCount; i++) { entityManager.persist( new Post() .setId(i) .setTitle( String.format( "High-Performance Java Persistence, review no. %1$d", i ) ) );}

Pour activer les insertions par lots JDBC, il suffit de fournir une seule propriété de configuration:

<property name="hibernate.jdbc.batch_size" value="50"/>

Une fois cette propriété fournie, Hibernate peut passer automatiquement du non-traitement par lots au traitement par lots sans avoir besoin de modifier le code d’accès aux données.

Et, pour récupérer les 10 premières lignes post, nous pouvons exécuter la requête JPQL suivante:

int maxResults = 10;List<Post> posts = entityManager.createQuery(""" select p from post p order by p.id """, Post.class).setMaxResults(maxResults).getResultList();

Si vous comparez cela à la version JDBC, vous verrez que JPA est beaucoup plus facile à utiliser.

Les avantages et les inconvénients de l’utilisation de JPA et Hibernate

JPA, en général, et Hibernate, en particulier, offrent de nombreux avantages.

  • Vous pouvez récupérer des entités ou des DTO. Vous pouvez même récupérer une projection DTO parent-enfant hiérarchique.
  • Vous pouvez activer le traitement par lots JDBC sans modifier le code d’accès aux données.
  • Vous avez la prise en charge du verrouillage optimiste.
  • Vous avez une abstraction de verrouillage pessimiste indépendante de la syntaxe spécifique à la base de données sous-jacente, de sorte que vous pouvez acquérir un VERROU de LECTURE et d’ÉCRITURE ou même un VERROU DE SAUT.
  • Vous disposez d’une API de pagination indépendante de la base de données.
  • Vous pouvez fournir un List de valeurs à une clause IN query, comme expliqué dans cet article.
  • Vous pouvez utiliser une solution de mise en cache fortement cohérente qui vous permet de décharger le nœud principal, qui, pour les transactions d’écriture réa, ne peut être appelé que verticalement.
  • Vous avez une prise en charge intégrée de la journalisation des audits via Hibernate Envers.
  • Vous avez une prise en charge intégrée de la multitenance.
  • Vous pouvez générer un script de schéma initial à partir des mappages d’entités à l’aide de l’outil Hibernate hbm2ddl, que vous pouvez fournir à un outil de migration automatique de schéma, comme Flyway.
  • Non seulement vous avez la liberté d’exécuter n’importe quelle requête SQL native, mais vous pouvez utiliser le SqlResultSetMapping pour transformer le JDBC ResultSet en entités JPA ou DTO.

Les inconvénients de l’utilisation de JPA et Hibernate sont les suivants:

  • Bien que commencer avec JPA soit très facile, devenir un expert nécessite un investissement de temps important car, outre la lecture de son manuel, vous devez toujours apprendre comment fonctionnent les systèmes de base de données, le standard SQL ainsi que la saveur SQL spécifique utilisée par votre base de données de relations de projet.
  • Il existe des comportements moins intuitifs qui pourraient surprendre les débutants, comme l’ordre d’opération de rinçage.
  • L’API Criteria est plutôt verbeuse, vous devez donc utiliser un outil comme Codota pour écrire plus facilement des requêtes dynamiques.

La communauté globale et les intégrations populaires

JPA et Hibernate sont extrêmement populaires. Selon le rapport sur l’écosystème Java 2018 de Snyk, Hibernate est utilisé par 54% de tous les développeurs Java qui interagissent avec une base de données relationnelle.

Ce résultat peut être soutenu par Google Trends. Par exemple, si nous comparons les tendances Google de JPA par rapport à ses principaux concurrents (par exemple, MyBatis, QueryDSL et jOOQ), nous pouvons voir que JPA est beaucoup plus populaire et ne montre aucun signe de perte de sa position dominante de part de marché.

 Pourquoi et quand utiliser JPA

 Pourquoi et quand utiliser JPA

Être si populaire apporte de nombreux avantages, comme:

  • L’intégration JPA de Spring Data fonctionne comme un charme. En fait, l’une des principales raisons pour lesquelles JPA et Hibernate sont si populaires est que Spring Boot utilise Spring Data JPA, qui, à son tour, utilise Hibernate en coulisses.
  • Si vous rencontrez un problème, il y a de fortes chances que ces réponses StackOverflow 30k liées à l’hibernation et les réponses StackOverflow 16k liées à JPA vous fournissent une solution.
  • Il y a 73k tutoriels d’hibernation disponibles. Seul mon site propose à lui seul plus de 250 tutoriels JPA et Hibernate qui vous apprennent à tirer le meilleur parti de JPA et Hibernate.
  • Il existe également de nombreux cours vidéo que vous pouvez utiliser, comme mon cours vidéo de persistance Java haute performance.
  • Il y a plus de 300 livres sur Hibernate sur Amazon, dont l’un est également mon livre de persistance Java haute performance.

Alternatives JPA

L’une des plus grandes choses de l’écosystème Java est l’abondance de frameworks de haute qualité. Si JPA et Hibernate ne conviennent pas à votre cas d’utilisation, vous pouvez utiliser l’un des frameworks suivants:

  • MyBatis, qui est un framework de mappage de requêtes SQL très léger.
  • QueryDSL, qui vous permet de créer dynamiquement des requêtes SQL, JPA, Lucene et MongoDB.
  • jOOQ, qui fournit un métamodèle Java pour les tables sous-jacentes, les procédures stockées et les fonctions et vous permet de créer une requête SQL de manière dynamique à l’aide d’un DSL très intuitif et d’une manière sûre.

Alors, utilisez ce qui vous convient le mieux.

Ateliers en ligne

Si vous avez apprécié cet article, je parie que vous allez adorer mon prochain Atelier en ligne de persistance Java haute Performance de 4 jours x 4 heures

Conclusion

Dans cet article, nous avons vu pourquoi JPA a été créé et quand vous devriez l’utiliser. Bien que JPA apporte de nombreux avantages, vous avez de nombreuses autres alternatives de haute qualité à utiliser si JPA et Hibernate ne conviennent pas mieux aux exigences actuelles de votre application.

Et, parfois, comme je l’ai expliqué dans cet échantillon gratuit de mon livre de persistance Java haute Performance, vous n’avez même pas à choisir entre JPA ou d’autres frameworks. Vous pouvez facilement combiner JPA avec un framework comme jOOQ pour obtenir le meilleur des deux mondes.

 eBook sur les Transactions et le Contrôle de la Concurrence

 Roches de persistance Java hautes performances!
 Atelier en Ligne de Persistance Java Haute Performance
 Optimiseur d'hypersistance rocks!

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.