Qu'est-ce que l'hibernation ? Principes fondamentaux de la mise en œuvre d'Hibernate Core

Publié: 2013-04-17

Exemple d'hibernation Java

Hibernate est un projet de framework de persistance Java open source. Effectuez de puissants mappages relationnels d'objets et interrogez des bases de données à l'aide de HQL et de SQL.

En général, les bibliothèques largement utilisées sont bien conçues et implémentées, et il est très intéressant d'en apprendre quelques bonnes pratiques de codage.

Jetons un coup d'œil à l'intérieur de la bibliothèque principale d'hibernate et découvrons certaines de ses clés de conception.

Dans cet article, Hibernate Core est analysé par JArchitect pour approfondir sa conception et sa mise en œuvre.

Forfait par fonctionnalité

Package-by-feature utilise des packages pour refléter l'ensemble de fonctionnalités. Il place tous les éléments liés à une seule fonctionnalité (et uniquement cette fonctionnalité) dans un seul répertoire/package. Il en résulte des emballages avec une cohésion élevée et une grande modularité, et avec un couplage minimal entre les emballages. Les éléments qui fonctionnent étroitement ensemble sont placés les uns à côté des autres.

Hibernate core contient de nombreux packages, chacun étant lié à une fonctionnalité spécifique hql, sql et autres.

Forfaits Hibernate Core - Crunchify.com

Couplage

Un faible couplage est souhaitable car un changement dans un domaine d'une application nécessitera moins de changements dans l'ensemble de l'application. À long terme, cela pourrait réduire considérablement le temps, les efforts et les coûts associés à la modification et à l'ajout de nouvelles fonctionnalités à une application.

Voici trois avantages clés tirés de l'utilisation d'interfaces :

  • Une interface permet de définir un contrat favorisant la réutilisation. Si un objet implémente une interface, cet objet doit se conformer à une norme. Un objet qui utilise un autre objet est appelé un consommateur. Une interface est un contrat entre un objet et son consommateur.
  • Une interface fournit également un niveau d'abstraction qui facilite la compréhension des programmes. Les interfaces permettent aux développeurs de commencer à parler de la manière générale dont le code se comporte sans avoir à entrer dans de nombreuses spécificités détaillées.
  • Une interface applique un faible couplage entre les composants, ce qui facilite la protection du consommateur d'interface contre tout changement d'implémentation dans les classes implémentant les interfaces.

Cherchons toutes les interfaces définies par Hibernate Core, pour cela nous utilisons CQLinq pour interroger la base de code.

jboss11- Crunchify.com

Si notre objectif principal est d'appliquer un couplage faible, il y a une erreur courante lors de l'utilisation d'interfaces qui pourrait tuer l'utilité de les utiliser. C'est l'utilisation des classes concrètes au lieu des interfaces, et pour mieux expliquer ce problème prenons l'exemple suivant :

La classe A implémente l'interface IA qui contient la méthode calculate(), la classe consommateur C est implémentée comme ça

La classe C au lieu de référencer l'interface IA, elle référence la classe A, dans ce cas on perd le bénéfice du couplage faible, et cette implémentation a deux inconvénients majeurs :

  • Si nous décidons d'utiliser une autre implémentation d'IA, nous devons changer le code de la classe C.
  • Si certaines méthodes sont ajoutées à A qui n'existe pas dans IA, et que C les utilise, nous perdons également l'avantage contractuel de l'utilisation d'interfaces.

C # a introduit la capacité d'implémentation d'interface explicite dans le langage pour garantir qu'une méthode de l'IA ne sera jamais appelée à partir d'une référence à des classes concrètes, mais uniquement à partir d'une référence à l'interface. Cette technique est très utile pour empêcher les développeurs de perdre le bénéfice de l'utilisation des interfaces.

Avec JArchitect, nous pouvons vérifier ce genre d'erreurs en utilisant CQLinq , l'idée est de rechercher toutes les méthodes à partir de classes concrètes utilisées directement par d'autres méthodes.

Détails de hibernate2 - Crunchify.com

Par exemple la méthode getEntityPersister de SessionFactoryImpl qui implémente l'interface SessionFactoryImplementor est concernée par ce problème.

Recherchons des méthodes appelant directement SessionFactoryImpl.getEntityPersister.

Hiberner Tutoriel - Crunchify.com

Des méthodes comme SessionImpl.instantiate invoquent directement getEntityPersister, au lieu de passer par interface, ce qui casse le bénéfice d'utiliser des interfaces. Heureusement, le noyau d'hibernation ne contient pas beaucoup de méthodes ayant ce problème.

Couplage avec des bocaux externes

Lorsque des libs externes sont utilisées, mieux vaut vérifier si on peut facilement changer une lib tierce par une autre sans impacter toute l'application, il y a de nombreuses raisons qui peuvent nous inciter à changer une lib tierce.

L'autre bibliothèque pourrait :

  • Avoir plus de fonctionnalités
  • Plus puissant
  • Plus sécurisé

Prenons l'exemple de antlr lib qui servait à parser les requêtes hql, et imaginons qu'un autre parseur plus puissant qu'antlr ait été créé, pourrions-nous changer l'antlr par le nouveau parseur facilement ?

Pour répondre à cette question, recherchons quelles méthodes d'hibernate l'utilisent directement :

Détails de l'hibernation - Crunchify

Et lesquels l'ont utilisé indirectement :

Hibernate Funda - Tutoriels Java - Crunchify

De nombreuses méthodes utilisent antlr directement, ce qui rend le noyau d'hibernation fortement couplé avec lui, et changer antlr avec un autre n'est pas une tâche facile. ce fait ne signifie pas que nous avons un problème dans la conception de l'hibernation, mais nous devons être prudents lorsque nous utilisons une bibliothèque tierce et bien vérifier si une bibliothèque tierce doit être faiblement couplée ou non avec l'application.

Cohésion

Le principe de responsabilité unique stipule qu'une classe doit avoir une, et une seule, raison de changer. Une telle classe est dite cohésive. Une valeur LCOM élevée indique généralement une classe peu cohérente. Il existe plusieurs métriques LCOM. Le LCOM prend ses valeurs dans la plage [0-1]. Le LCOMHS (HS signifie Henderson-Sellers) prend ses valeurs dans la plage [0-2]. Notez que la métrique LCOMHS est souvent considérée comme plus efficace pour détecter les types non cohésifs.

Une valeur LCOMHS supérieure à 1 doit être considérée comme alarmante.

En général les classes les plus concernées par la cohésion sont les classes ayant beaucoup de méthodes et de domaines.

Recherchons des types ayant de nombreuses méthodes et champs.

hibernate6 - Crunchifier

Seuls quelques types sont concernés par cette requête, et pour tous le LCOMHS est inférieur à 1.

Utilisation des annotations

Le développement basé sur les annotations soulage les développeurs Java de la lourdeur de la configuration. Et donnez-nous une fonctionnalité puissante pour libérer le code source du code passe-partout. Le code résultant est également moins susceptible de contenir des bogues.

Recherchons toutes les annotations définies par le noyau d'hibernation.

hibernate7 - Crunchify.com

De nombreuses annotations sont définies, ce qui rend l'hibernation facile à utiliser par les développeurs, et le casse-tête des fichiers de configuration est évité.

Conclusion

Hibernate Core est un bon exemple de projets open source dont s'inspirer, n'hésitez pas à y jeter un œil.