web-dev-qa-db-fra.com

Hibernate ou JDBC

J'ai un client lourd, Java swing application avec un schéma de 25 tables et ~ 15 JInternalFrames (formulaires de saisie de données pour les tables). Je dois faire un choix de conception de JDBC ou ORM ( hibernation avec le framework Spring dans ce cas) pour l'interaction SGBD.

La mise en veille prolongée serait-elle exagérée pour un projet de cette taille? Une explication de la réponse oui ou non serait très appréciée (ou même une approche différente si cela se justifiait).

TIA.

68
jmq

Bonne question sans réponse simple.

J'étais un grand fan d'Hibernate après l'avoir utilisé dans plusieurs projets sur plusieurs années. J'avais l'habitude de croire que tout projet devrait par défaut hiberner.

Aujourd'hui, je n'en suis pas si sûr.

Hibernate (et JPA) est idéal pour certaines choses, en particulier au début du cycle de développement. Il est beaucoup plus rapide d'arriver à quelque chose qui fonctionne avec Hibernate qu'avec JDBC. Vous bénéficiez de nombreuses fonctionnalités gratuites: mise en cache, verrouillage optimiste, etc.

D'un autre côté, cela a des coûts cachés. Hibernate est d'une simplicité trompeuse lorsque vous démarrez. Suivez un didacticiel, mettez des annotations sur votre classe - et vous avez la persévérance. Mais ce n'est pas simple et pour pouvoir y écrire du bon code, il faut bien comprendre à la fois son fonctionnement interne et la conception de la base de données. Si vous venez de commencer, vous ne connaissez peut-être pas certains problèmes qui pourraient vous mordre plus tard, alors voici une liste incomplète.

Performance

Les performances d'exécution sont assez bonnes, je n'ai pas encore vu de situation où l'hibernation était la raison de mauvaises performances dans la production . Le problème est la performance de démarrage et comment elle affecte votre temps de test unitaire et les performances de développement. Lorsque hibernate se charge, il analyse toutes les entités et fait beaucoup de pré-mise en cache - cela peut prendre environ 5-10-15 secondes pour une application pas très grande. Donc, votre test unitaire d'une seconde va prendre 11 secods maintenant. Pas drôle.

Indépendance de la base de données

C'est très cool tant que vous n'avez pas besoin de faire un réglage fin sur la base de données.

Session en mémoire

Pour chaque transaction, Hibernate stockera un objet en mémoire pour chaque ligne de base de données qu'il "touche". C'est une belle optimisation lorsque vous effectuez une simple saisie de données. Si vous avez besoin de traiter de nombreux objets pour une raison quelconque, cela peut sérieusement affecter les performances, à moins que vous ne nettoyiez vous-même explicitement et soigneusement la session en mémoire.

Cascades

Les cascades vous permettent de simplifier le travail avec les graphiques d'objets. Par exemple, si vous avez un objet racine et des enfants et que vous enregistrez l'objet racine, vous pouvez également configurer hibernate pour enregistrer les enfants. Le problème commence lorsque votre graphique d'objet devient complexe. À moins que vous soyez extrêmement prudent et que vous compreniez bien ce qui se passe en interne, il est facile de gâcher cela. Et lorsque vous le faites, il est très difficile de déboguer ces problèmes.

Chargement paresseux

Le chargement différé signifie que chaque fois que vous chargez un objet, hibernate ne chargera pas tous ses objets associés mais fournira à la place des espaces réservés qui seront résolus dès que vous essayez d'y accéder. Grande optimisation non? C'est le cas, sauf que vous devez être conscient de ce comportement sinon vous obtiendrez des erreurs cryptiques. Google "LazyInitializationException" pour un exemple. Et soyez prudent avec les performances. Selon l'ordre dans lequel vous chargez vos objets et votre graphique d'objet, vous pouvez cliquer sur "n + 1 sélectionne le problème". Utilisez Google pour plus d'informations.

Mises à niveau du schéma

Hibernate permet des changements de schéma faciles en refactorisant simplement Java et redémarrage. C'est bien lorsque vous démarrez. Mais ensuite vous publiez la version un. Et à moins que vous ne vouliez perdre vos clients, vous devez leur fournir une mise à niveau du schéma Cela signifie qu'il n'y a plus de refactorisation simple car toutes les modifications de schéma doivent être effectuées en SQL.

Vues et procédures stockées

Hibernate nécessite un accès en écriture exclusif aux données avec lesquelles il travaille. Ce qui signifie que vous ne pouvez pas vraiment utiliser les vues, les procédures stockées et les déclencheurs, car ceux-ci peuvent entraîner des modifications des données avec hibernate qui ne les connaît pas. Certains processus externes peuvent écrire des données dans la base de données dans des transactions distinctes. Mais si vous le faites, votre cache contiendra des données non valides. Ce qui est une chose de plus à se soucier.

sessions à thread unique

Les sessions de mise en veille prolongée sont monothread. Tout objet chargé via une session est uniquement accessible (y compris la lecture) à partir du même thread. Ceci est acceptable pour les applications côté serveur mais peut compliquer les choses inutiles si vous faites une application basée sur une interface graphique.

Je suppose que mon point est que il n'y a pas de repas gratuits.

Hibernate est un bon outil, mais c'est un outil complexe, et il faut du temps pour bien le comprendre. Si vous ou les membres de votre équipe ne disposez pas de telles connaissances, il peut être plus simple et plus rapide d'utiliser JDBC pur (ou Spring JDBC) pour une seule application. D'un autre côté, si vous êtes prêt à investir du temps dans son apprentissage (y compris l'apprentissage par la pratique et le débogage) qu'à l'avenir, vous serez en mesure de mieux comprendre les compromis.

184
Gregory Mostizky

La mise en veille prolongée peut être bonne, mais elle et d'autres ORM JPA ont tendance à dicter votre structure de base de données dans une certaine mesure. Par exemple, les clés primaires composites peuvent être effectuées dans Hibernate/JPA mais elles sont un peu gênantes. Il y a d'autres exemples.

Si vous êtes à l'aise avec SQL, je vous suggère fortement de jeter un œil à Ibatis . Il peut faire 90% + de ce que peut faire Hibernate mais est beaucoup plus simple à implémenter.

Je ne peux pas penser à une seule raison pour laquelle je choisirais JDBC (ou même Spring JDBC) plutôt que Ibatis. Hibernate est un choix plus complexe.

Jetez un œil au Tutoriel Spring et Ibatis .

20
cletus

Hibernate a sans aucun doute sa complexité.

Mais ce que j'aime vraiment dans l'approche Hibernate (d'autres aussi), c'est que le modèle conceptuel que vous pouvez obtenir dans Java est meilleur. Bien que je ne considère pas OO comme une panacée, et je ne recherche pas la pureté théorique du design, j'ai trouvé tellement de fois que OO simplifie en fait mon code . Comme vous avez demandé spécifiquement des détails, voici quelques exemples:

  • le la complexité ajoutée n'est pas dans le modèle et les entités, mais dans votre framework pour manipuler toutes les entités par exemple. Pour les responsables, la partie dure n'est pas quelques classes de framework mais votre modèle, donc Hibernate vous permet de garder la partie dure (le modèle) à son niveau le plus propre.

  • si un champ (comme un identifiant ou des champs d'audit, etc.) est utilisé dans toutes vos entités, vous pouvez créer un superclasse avec lui. Donc :

    • vous écrivez moins de code, mais plus important encore ...
    • il y a moins de concepts dans votre modèle (le concept unique est unique dans le code)
    • gratuitement, vous pouvez écrire du code plus générique, celui fourni avec une entité (inconnu, pas de changement de type ou de cast), vous permet d'accéder à l'id.
  • Hibernate possède également de nombreuses fonctionnalités pour gérer les autres caractéristiques du modèle dont vous pourriez avoir besoin (maintenant ou plus tard, ajoutez-les uniquement si nécessaire). Prenez-le comme une qualité extensibilité pour votre conception.

    • Vous pouvez remplacer l'héritage (sous-classement) par la composition (plusieurs entités ayant un même membre, qui contient quelques champs associés qui s'avèrent nécessaires dans plusieurs entités).
    • Il peut y avoir un héritage entre quelques-unes de vos entités. Il arrive souvent que vous ayez deux tables qui ont à peu près la même structure (mais vous ne voulez pas stocker toutes les données dans une table, car vous perdriez l'intégrité référentielle dans une table parent différente).
  • Avec la réutilisation entre vos entités (mais seulement héritage approprié et composition), il y a généralement des avantages supplémentaires à venir. Exemples :

    • il existe souvent un moyen de lire les données des entités qui est similaire mais différent. Supposons que je lise le champ "title" pour trois entités, mais pour certaines, je remplace le résultat par une valeur par défaut différente s'il est nul. Il est facile d'avoir une signature "getActualTitle" (dans une superclasse ou une interface), et d'implémenter la gestion des valeurs par défaut dans les trois implémentations. Cela signifie que le code de mes entités ne traite que du concept d'un "titre réel" (j'ai rendu ce concept fonctionnel explicite), et l'héritage de la méthode se charge d'exécuter le code correct (plus de commutateur ou si, pas de duplication de code) .
    • ...
  • Au fil du temps, les exigences évoluent. Il y aura un point où votre structure de base de données aura des problèmes. Avec JDBC seul, toute modification de la base de données doit avoir un impact sur le code (c'est-à-dire double coût). Avec Hibernate, de nombreux changements peuvent être absorbés en modifiant uniquement le mappage, pas le code. La même chose se produit dans l'autre sens: Hibernate vous permet de changer votre code (entre versions par exemple) sans altérer votre base de données (changer le mappage, même si ce n'est pas toujours suffisant). Pour résumer, Hibernate vous permet de faire évoluer votre base de données et votre code indépendamment.

Pour toutes ces raisons, je choisirais Hibernate :-)

12
KLE

Je pense que l'un ou l'autre est un bon choix, mais personnellement, j'utiliserais hibernate. Je ne pense pas que l'hibernation soit exagérée pour un projet de cette taille.

Là où Hibernate brille vraiment pour moi, c'est les relations entre les entités/tables. Faire JDBC à la main peut prendre beaucoup de code si vous traitez la modification du parent et des enfants (petits-enfants, frères et sœurs, etc.) en même temps. Hibernate peut en faire un jeu d'enfant (souvent une seule sauvegarde de l'entité parent suffit).

Cependant, il existe certainement des complexités lors de la gestion de Hibernate, telles que la compréhension du fonctionnement du vidage de session et la gestion du chargement paresseux.

5
Brian Yarger

Hibernate convient le mieux aux applications middleware. Supposons que nous construisons un middleware au-dessus de la base de données, Le middelware est accessible par environ 20 applications dans ce cas, nous pouvons avoir une mise en veille prolongée qui satisfait les exigences des 20 applications.

3
Asok B

Le JDBC droit conviendrait au mieux aux cas les plus simples.

Si vous voulez rester dans Java et OOD, alors aller Hibernate ou Hibernate/JPA ou tout autre fournisseur JPA/JPA devrait être votre choix.

Si vous êtes plus à l'aise avec SQL, avoir des modèles Spring pour JDBC et d'autres frameworks orientés SQL ne fera pas de mal.

En revanche, à part le contrôle transactionnel, Spring n'a pas beaucoup d'aide pour travailler avec JPA.

3
topchef
  1. Dans JDBC, si nous ouvrons une connexion à une base de données, nous devons écrire try, et si des exceptions se sont produites, catch block en prendra et finira par fermer les connexions.

  2. Dans jdbc, toutes les exceptions sont des exceptions vérifiées, nous devons donc écrire du code dans try, catch et throws, mais dans hibernate, nous n'avons que des exceptions non vérifiées

  3. Ici, en tant que programmeur, nous devons fermer la connexion, sinon nous aurons peut-être la chance de recevoir notre message de connexions…!

  4. En fait, si nous n'avons pas fermé la connexion dans le bloc enfin, jdbc n'est pas responsable de la fermer.

  5. Dans JDBC, nous devons écrire des commandes SQL à divers endroits, après que le programme a créé si la structure de la table est modifiée, le programme JDBC ne fonctionne pas, encore une fois, nous devons modifier et compiler et redéployer, ce qui est fastidieux.

  6. JDBC utilisé pour générer des codes d'erreur liés à la base de données si une exception se produit, mais Java ne connaissent pas correctement ces codes d'erreur.

  7. Pendant que nous insérons un enregistrement, si nous n'avons pas de table particulière dans la base de données, JDBC génère une erreur comme "View not exist" et lève une exception, mais en cas d'hibernation, s'il n'a trouvé aucune table dans le base de données cela va créer la table pour nous

  8. JDBC prend en charge le chargement LAZY et Hibernate prend en charge le chargement Eager

  9. Hibernate soutient l'héritage, les associations et les collections

  10. En hibernation, si nous sauvegardons l'objet de classe dérivé, son objet de classe de base sera également stocké dans la base de données, cela signifie que l'hibernation prend en charge l'héritage

  11. Hibernate prend en charge les relations comme un à plusieurs, un à un, plusieurs à plusieurs à plusieurs, plusieurs à un

  12. Hibernate prend en charge le mécanisme de mise en cache par ceci, le nombre d'aller-retour entre une application et la base de données sera réduit, en utilisant cette technique de mise en cache, les performances d'une application seront augmentées automatiquement

  13. La pagination en veille prolongée est assez simple.

  14. Hibernate a la capacité de générer automatiquement des clés primaires pendant que nous stockons les enregistrements dans la base de données

1
Creditto

... Session en mémoire ... LazyInitializationException ...

Vous pouvez regarder Ebean ORM qui n'utilise pas d'objets de session ... et où le chargement paresseux fonctionne. Certainement une option, pas exagérée, et sera plus simple à comprendre.

0
Rob Bygrave

si des milliards d'utilisateurs utilisent notre application ou notre site Web, la requête jdbc sera exécutée des milliards de fois, mais la requête en veille prolongée ne sera exécutée qu'une seule fois pour le nombre d'utilisateurs le plus important et le plus facile de la mise en veille prolongée par rapport à jdbc.

0
Ankesh Roy