web-dev-qa-db-fra.com

Hibernate, iBatis, Java EE ou autre Java ORM tool

Nous sommes en train de planifier une grande application d'entreprise. Nous concentrons nos efforts sur l'évaluation de l'hibernation après avoir éprouvé les douleurs de J2EE.

Il ressemble à la nouvelle Java EE API est plus simple. J'ai également lu de bonnes choses sur Hibernate et iBatis. Notre équipe a peu d'expérience avec aucun des frameworks.

Il y a 5 points de comparaison principaux que j'aimerais déterminer

  • Courbe d'apprentissage/facilité d'utilisation
  • Productivité
  • Maintenabilité/stabilité
  • Performance/évolutivité
  • Facilité de dépannage

Si vous deviez gérer une équipe de ~ 6 développeurs avec une expérience J2EE, quel outil ORM utiliseriez-vous et pourquoi?

66
Kevin Williams

Permettez-moi de prendre une fissure à ce sujet. Tout d'abord, j'en ai écrit sur ce sujet dans tilisation d'un ORM ou d'un SQL simple? . Plus précisément pour répondre à vos points:

Courbe d'apprentissage/Facilité d'utilisation

Ibatis concerne SQL. Si vous connaissez SQL, la courbe d'apprentissage pour ibatis est triviale. Ibatis fait certaines choses en plus de SQL telles que:

  • par groupe;
  • types discriminés; et
  • sQL dynamique.

que vous devrez encore apprendre, mais le plus gros obstacle est SQL.

JPA (qui inclut Hibernate) d'autre part essaie de se distancier de SQL et de présenter les choses dans un objet plutôt que de manière relationnelle. Comme le souligne cependant Joel, les abstractions fuient et JPA ne fait pas exception. Pour effectuer JPA, vous devez toujours connaître les modèles relationnels, SQL, l'optimisation des performances des requêtes, etc.

Alors qu'Ibatis vous demandera simplement d'appliquer le SQL que vous connaissez ou apprenez, JPA vous demandera de savoir autre chose: comment le configurer (XML ou annotations). J'entends par là comprendre que les relations de clé étrangère sont une relation (un à un, un à plusieurs ou plusieurs à plusieurs) d'une sorte, le mappage de type, etc.

Si vous connaissez SQL, je dirais que l'obstacle à l'apprentissage de JPA est en fait plus élevé. Si vous ne le faites pas, c'est plus un résultat mitigé avec JPA vous permettant de différer efficacement l'apprentissage de SQL pendant un certain temps (mais cela ne le retarde pas indéfiniment).

Avec JPA, une fois que vous avez configuré vos entités et leurs relations, les autres développeurs peuvent simplement les utiliser et n'ont pas besoin de tout savoir sur la configuration de JPA. Cela pourrait être un avantage, mais un développeur devra toujours connaître les gestionnaires d'entités, la gestion des transactions, les objets gérés par rapport aux objets non gérés, etc.

Il convient de noter que JPA possède également son propre langage de requête (JPA-SQL), dont vous aurez besoin pour savoir si vous connaissez ou non SQL. Vous trouverez des situations où JPA-SQL ne peut tout simplement pas faire les choses que SQL peut faire.

Productivité

C'est difficile à juger. Personnellement, je pense que je suis plus productif dans ibatis mais je suis aussi très à l'aise avec SQL. Certains diront qu'ils sont beaucoup plus productifs avec Hibernate, mais cela est probablement dû - au moins en partie - à une méconnaissance de SQL.

De plus, la productivité avec JPA est trompeuse car vous rencontrerez parfois un problème avec votre modèle de données ou vos requêtes qui vous prendra une demi-journée à résoudre pendant que vous activez la journalisation et regardez ce que votre fournisseur JPA produit et travaille ensuite la combinaison de paramètres et d'appels pour qu'il produise quelque chose à la fois correct et performant.

Vous n'avez tout simplement pas ce genre de problème avec Ibatis parce que vous avez écrit le SQL vous-même. Vous le testez en exécutant le SQL dans PL/SQL Developer, SQL Server Management Studio, Navicat pour MySQL ou autre. Une fois la requête correcte, tout ce que vous faites est de mapper les entrées et les sorties.

J'ai également trouvé que JPA-QL était plus gênant que SQL pur. Vous avez besoin d'outils séparés pour simplement exécuter une requête JPA-QL pour voir les résultats et c'est quelque chose de plus que vous devez apprendre. En fait, j'ai trouvé cette partie de JPA plutôt maladroite et lourde, bien que certaines personnes l'adorent.

Maintenabilité/stabilité

Le danger avec Ibatis ici est la prolifération, ce qui signifie que votre équipe de développement peut simplement continuer à ajouter des objets et des requêtes de valeur comme ils en ont besoin plutôt que de chercher à les réutiliser, tandis que JPA a une entité par table et une fois que vous avez cette entité, c'est tout. Les requêtes nommées ont tendance à aller sur cette entité et sont donc difficiles à manquer. Les requêtes ad hoc peuvent toujours être répétées, mais je pense que c'est moins un problème potentiel.

Cela se fait cependant au détriment de la rigidité. Souvent, dans une application, vous aurez besoin de morceaux de données provenant de différentes tables. Avec SQL, c'est facile, car vous pouvez écrire une seule requête (ou un petit nombre de requêtes) pour obtenir toutes ces données en une seule fois et les placer dans un objet de valeur personnalisé juste à cette fin.

Avec JPA, vous déplacez cette logique vers votre couche métier. Les entités sont essentiellement tout ou rien. Maintenant, ce n'est pas strictement vrai. Divers fournisseurs JPA vous permettront de charger partiellement des entités, etc., mais même là, vous parlez des mêmes droits discrets. Si vous avez besoin de données provenant de 4 tables, vous avez besoin de 4 entités ou vous devez combiner les données souhaitées dans une sorte d'objet de valeur personnalisé dans la couche métier ou présentation.

Une autre chose que j'aime chez ibatis est que tout votre SQL est externe (dans des fichiers XML). Certains citeront cela comme un inconvénient mais pas moi. Vous pouvez alors trouver des utilisations d'une table et/ou colonne relativement facile en recherchant vos fichiers XML. Avec SQL intégré dans le code (ou lorsqu'il n'y a pas de SQL du tout), il peut être beaucoup plus difficile à trouver. Vous pouvez également couper et coller du SQL dans un outil de base de données et l'exécuter. Je ne saurais trop insister sur le nombre de fois que cela m'a été utile au fil des ans.

Performances/évolutivité

Ici, je pense qu'ibatis gagne haut la main. C'est du SQL simple et à faible coût. De par sa nature, JPA ne sera tout simplement pas en mesure de gérer le même niveau de latence ou de débit. Maintenant, ce que JPA a à faire, c'est que la latence et le débit ne sont que rarement des problèmes. Cependant, des systèmes à hautes performances existent et auront tendance à défavoriser les solutions plus lourdes comme JPA.

De plus, avec ibatis, vous pouvez écrire une requête qui renvoie exactement les données souhaitées avec les colonnes exactes dont vous avez besoin. Fondamentalement, il n'y a aucun moyen que JPA puisse battre (ou même faire correspondre) cela lorsqu'il renvoie des entités discrètes.

Facilité de dépannage

Je pense que celui-ci est également une victoire pour Ibatis. Comme je l'ai mentionné ci-dessus, avec JPA, vous passerez parfois une demi-journée à obtenir une requête ou une entité pour produire le SQL souhaité ou à diagnostiquer un problème où une transaction échoue parce que le gestionnaire d'entité a tenté de conserver un objet non géré (qui pourrait faire partie d'un lot). travail où vous avez engagé beaucoup de travail, il pourrait donc être non trivial de trouver).

Les deux échoueront si vous essayez d'utiliser une table ou une colonne qui n'existe pas, ce qui est bien.

Autres critères

Maintenant, vous n'avez pas mentionné la portabilité comme l'une de vos exigences (c'est-à-dire le déplacement entre les fournisseurs de bases de données). Il convient de noter qu'ici, JPA a l'avantage. Les annotations sont moins portables que, disons, Hibernate XML (par exemple, les annotations JPA standard n'ont pas d'équivalent pour le type d'ID "natif" d'Hibernate) mais les deux sont plus portables qu'ibatis/SQL.

J'ai également vu JPA/Hibernate utilisé comme une forme de DDL portable, ce qui signifie que vous exécutez un petit programme Java qui crée le schéma de base de données à partir de la configuration JPA. Avec ibatis, vous aurez besoin d'un script pour chaque base de données prise en charge.

L'inconvénient de la portabilité est que JPA est, à certains égards, le plus petit dénominateur commun, ce qui signifie que le comportement pris en charge est largement le comportement pris en charge par un large éventail de fournisseurs de bases de données. Si vous souhaitez utiliser Oracle Analytics dans ibatis, pas de problème. En JPA? Eh bien, c'est un problème.

112
cletus

Une règle de base simpliste entre iBatis et Hibernate est que si vous voulez plus de vues SQL/relationnelles du monde, iBatis est mieux adapté; et pour une chaîne d'héritage plus complexe, et une vue moins directe sur SQL, Hibernate. Les deux sont de bons cadres largement utilisés et solides. Je pense donc que les deux fonctionneraient probablement bien. Peut-être lisez un tutoriel pour les deux, voyez si l'un sonne mieux que l'autre, et choisissez-en un.

Parmi les choses que vous énumérez, je ne pense pas que les performances soient très différentes - le goulot d'étranglement sera presque toujours la base de données, pas le framework. Pour d'autres choses, je pense que différents développeurs préféreraient l'un ou l'autre, c'est-à-dire qu'il n'y a pas de priorité communément acceptée (pour iBatis vs Hibernate).

11
StaxMan

La solution que vous choisissez dépend également de la conformité que vous choisissez (ou êtes requis) avec la spécification Java EE. JPA est "la norme" pour l'accès aux données dans Java EE, donc si vous êtes particulièrement attaché à cela, vous devriez l'utiliser (avec quelques mises en garde).

JPA est une normalisation des systèmes de cartographie relationnelle-objet. En tant que tel, il ne fournit pas d'implémentation, il définit simplement une approche standardisée. Hibernate Entity Manager est l'une de ces implémentations.

Étant donné que JPA est une norme pour plusieurs fournisseurs et qu'il est encore relativement nouveau, il lui manque des fonctionnalités plus ésotériques qui sont précieuses dans certains cas d'utilisation (par exemple, une API Criteria pour générer du SQL dynamique). Si vous optez pour JPA, planifiez des situations où vous devrez utiliser directement Hibernate, ou même JDBC directement. Pour de telles situations, un modèle DAO générique est très utile; vous pouvez modifier celui-ci: Objets d'accès aux données génériques pour une utilisation dans JPA et JDBC assez facilement.

JPA a des restrictions difficiles (en particulier si vous êtes habitué à la mise en veille prolongée) et vous impose certaines approches qui sont difficiles pour les développeurs qui sont plus habitués à écrire directement JDBC. Si vous défendez cela comme une approche, assurez-vous de faire vos devoirs sur les avantages contre les inconvénients de l'ORM contre JDBC.

Si vous optez pour JPA, une fois que vous aurez atteint la courbe d'apprentissage, cela sera payant en termes de développement simple (en particulier si vous implémentez correctement le modèle DAO susmentionné), mais également en obtenant une mise en cache à plusieurs niveaux des résultats de la requête. Si c'est fait correctement (un grand "si", je sais), j'ai vu que cela offrait de beaux avantages.

Enfin, si vous avez un modèle de données hérité avec lequel vous avez peu de flexibilité, Hibernate (et JPA) vous donnera plus de maux de tête que cela ne vaut peut-être. Par exemple:

  • Si la base de données n'a pas de clés primaires candidates (pour des implémentations efficaces de hashCode et égal), vous devrez faire une analyse initiale sur quelles colonnes définissent une ligne de manière unique - peut-être simple, peut-être complexe selon la complexité de votre schéma;
  • Si vous ne parvenez pas à ajouter des colonnes de version ou d'horodatage, vous perdez la capacité d'Hibernate à effectuer un verrouillage optimiste et finissez par devoir interroger avant la mise à jour.

(Ajouté en réponse au premier commentaire) Si vous avez la chance de reconcevoir votre base de données, deux considérations très importantes si vous voulez être en utilisant un ORM:

  • Ajoutez une colonne de numéro de version à toutes les tables pertinentes pour prendre en charge un verrouillage optimiste.
  • Lors de votre analyse des données, choisissez les colonnes " clé alternative " non nullables que les développeurs doivent utiliser pour hashCode() & equals(). N'utilisez pas de colonnes PK dans ces méthodes.
7

Pour ajouter une autre option à la liste ... jetez un œil à:

Ebean ORM ( http://ebean-orm.github.io ).

Sa principale revendication serait un modèle de programmation plus simple et plus intuitif que JPA ou Hibernate. Plus précisément, il n'a pas de session Hibernate ou JPA EntityManager, pas d'objets détachés/attachés (pas de fusion, persistance, vidage), le chargement paresseux fonctionne.

... aka beaucoup plus simple à utiliser et à comprendre.

Vous pouvez également utiliser votre propre SQL avec Ebean (pour les requêtes, les mises à jour, les procédures stockées) et IMO il correspond à Ibatis dans la facilité d'utilisation par rapport à votre propre SQL.

Si vous cherchez à utiliser l'ORM dans Java SE alors je vous suggère de le vérifier.

  • Licence LGPL
  • Utiliser des annotations JPA pour le mappage (@Entity, @OneToMany etc.)
  • API sans session (pas de fusion, persistance, vidage ... save () et delete () à la place)
  • Prise en charge des "objets partiels"
  • Prise en charge des requêtes volumineuses (par contexte de persistance du graphique d'objet)
  • Requêtes en arrière-plan
  • Bon support pour le traitement par lots
  • Réglage automatique des requêtes (via "Autofetch")

À la vôtre, Rob.

6
Rob Bygrave

Nous travaillons actuellement sur un projet qui utilise à la fois Hibernate et ibatis. Pourquoi utiliser hibernate? Il prend en charge notre modèle de domaine, nos relations et notre héritage. Nous avons un modèle de domaine assez complexe et hiberante le supporte très bien. Pas besoin de s'inquiéter de la rédaction d'inserts, de mises à jour, etc. Ibatis est utilisé uniquement pour la visualisation. Il existe des requêtes et nous avons des objets de vue (similaires aux modèles de domaine mais pas aux modèles de domaine) qui sont mappés avec des requêtes. Ibatis renvoie les données dans la vue obejct que vous souhaitez sans vous soucier de la lecture de l'ensemble de résultats, que vous devez gérer dans Spring JDBC. Pourquoi faisons-nous cela au lieu d'utiliser HQl ou Spring JDBC? Le domaine est tellement complexe et lors du rendu de la vue, nous faisons des calculs, regroupons et des tonnes de fonctions SQL natives. nous faisons tout cela dans les requêtes, utilisons des requêtes dynamiques, gérons les conditions dans ibatis et obtenons un objet propre et léger. Cela a beaucoup plus de sens si vous devez parcourir plusieurs couches pour récupérer des données en veille prolongée. En fonction de votre situation, vous pouvez donc en utiliser une seule, ou les deux, voire aucune. Mais définitivement, l'hibernation n'est pas quelque chose dont vous ne pouvez pas vous passer.

5
vsingh

Sachez que l'utilisation de JPA/Hibernate (et probablement de la plupart des autres solutions ORM) dans des applications multithread non triviales peut rapidement devenir un véritable PITA car les sessions de base de données doivent être confinées à un seul thread (les objets Session ne sont pas thread-safe). Ajoutez le chargement paresseux et le fait que les entités persistantes peuvent appartenir à au plus une session active ... et vous êtes prêt pour un sacré tour ...

Vous voudrez peut-être jeter un œil à Gestion de session en utilisant Hibernate dans une application Swing * multi-threaded * (ou recherchez simplement 'hibernate multi-threaded').

Ma règle de base (YMMV): Si l'application ne se prête pas à une sorte de cycle de demande/réponse (comme un webservice par exemple), il vaut probablement mieux utiliser autre chose.

Bien entendu, une autre solution consisterait à concevoir l'application de manière à contourner les limitations du cadre mentionnées. Changer la conception d'une application pour que je puisse faire fonctionner le framework XYZ laisse cependant un mauvais arrière-goût.

Quoi qu'il en soit, juste mon 0,02 $

4
JavaGuy

Je pense que nous devrions prendre en considération la principale raison pour laquelle nous utilisons Java (ou OO).

Le système doit être flexible et permettre des modifications constantes des spécifications (cela se produit très souvent dans la vie réelle). Sinon, nous aurions dû programmer en C, car c'est beaucoup plus rapide.

Je pense que la meilleure pile pour les applications Web serait Java EE: JPA - EJB - JSF (avec une portée de conversation de contexte de persistance étendue).

JSF est également plus lent que JSP/Servlet pur, mais il est plus rapide à développer.

JPA est plus difficile à apprendre, mais il est plus rapide à développer (vous savez: RAD) et les changements n'ont pas d'impact important (copier-coller sujet aux erreurs). Ajoutez une nouvelle colonne dans votre entité la plus utilisée et vous devrez mettre à jour toutes les instructions dans iBatis ...

JPA ne fonctionne pas très bien dans tous les cas, mais il couvre la plupart d'entre eux, et il vous permet également de brancher Native Query au lieu de JPQL sans changer de code. Mais si vous vous trouvez en train d'écrire trop de requêtes natives, votre projet pourrait mieux convenir à iBatis.

. générera trop de requêtes. Il n'y a pas de magie! Vous devez être au courant de la requête générée, et ne pas espérer aveuglément que vous pourrez prendre le chemin facile lorsqu'un cas compliqué pourrait apparaître.

. JPA doit être utilisé pour conserver votre modèle, pas pour Business Logic.

La requête de critères ne correspond pas non plus à la création de requêtes dynamiques nomatterhowcomplex sécurisées.

4
Cosmin Cosmin

Si vous avez en effet un projet greenfield, vous pouvez utiliser hibernate, mais sachez que la courbe d'apprentissage est assez raide.

Si vous avez une base de données existante, vous êtes beaucoup mieux avec iBatis, car après un jour, vous êtes productif et après deux jours de plus, vous pouvez tout savoir.

Une chose que vous devez considérer est que l'api des critères d'hibernation est excellent pour créer des requêtes personnalisées, ce qui, selon votre application, peut être un bon argument pour cela.

3
Mauli

Je suggère d'aller avec JPA et en fonction (fortement!) De la durée/portée de votre projet, vous pourriez aussi bien regarder dans JPA2, car il fournit certaines des fonctionnalités manquantes de JPA (une API de requête très agréable par exemple).

2
Joachim Sauer

Si vous n'avez pas un bon modèle d'objet, je ne vois pas l'avantage d'Hibernate. Vous avez certainement le "relationnel" dans ORM, car vous avez une base de données relationnelle, mais "l'objet" est la clé. Pas d'objets, pas d'ORM. Je pense qu'une cartographie 1: 1 entre les objets et les tables, sans un comportement d'objet plus riche, ne justifie pas l'ORM. Restez avec JDBC ou iBatis si tel est votre cas.

2
duffymo

Allez en veille prolongée. Votre projet augmentera certainement plus tard et l'investissement (sur l'apprentissage de l'hibernation) sera payant d'une manière ou d'une autre.

1
cherouvim