Que pensez-vous d'un nouvel outil de persistance Java, qui n'est pas vraiment un ORM? [fermé]

12

Persistance en Java

Au cours des dernières années, j'ai acquis une expérience dans le domaine de l'abstraction de persistance en Java, en utilisant des concepts tels que EJB 2.0, Hibernate, JPA et ceux développés localement. Ils me semblaient avoir une courbe d'apprentissage abrupte et beaucoup de complexité. De plus, en tant que grand fan de SQL, je pensais également que de nombreux modèles d'abstraction fournissent trop d'abstraction sur SQL, créant des concepts tels que "critères", "prédicats", "restrictions" qui sont de très bons concepts, mais pas SQL.

L'idée générale de l'abstraction de persistance en Java semble être basée sur le modèle relationnel-objet, où les SGBDR sont en quelque sorte mis en correspondance avec le monde OO. Le débat ORM a toujours été émotionnel, car il ne semble pas exister de solution unique qui convienne à tout le monde - si une telle solution peut même exister.

jOOQ

Ma préférence personnelle sur la façon d'éviter les problèmes liés à l'ORM est de m'en tenir au monde relationnel. Maintenant, le choix du paradigme du modèle de données ne devrait pas être le sujet de discussion car c'est une préférence personnelle, ou une question de quel modèle de données convient le mieux à un problème concret. La discussion que je voudrais lancer concerne mon propre outil de persistance appelé jOOQ . J'ai conçu jOOQ pour offrir la plupart des avantages des outils de persistance modernes:

  • Un langage spécifique au domaine basé sur SQL
  • Génération de code source mappant le schéma de base de données sous-jacent à Java
  • Prise en charge de nombreux SGBDR

Ajout de certaines fonctionnalités que peu d'outils de persistance modernes ont (corrigez-moi si je me trompe):

  • Prise en charge de SQL complexe - unions, sélections imbriquées, auto-jointures, alias, clauses de casse, expressions arithmétiques
  • Prise en charge de SQL non standard - procédures stockées, UDT, ENUMS, fonctions natives, fonctions analytiques

Veuillez consulter la page de documentation pour plus de détails: http://www.jooq.org/learn.php . Vous verrez qu'une approche très similaire est implémentée dans Linq pour C #, bien que Linq ne soit pas exclusivement conçu pour SQL.

La question

Maintenant, après avoir dit que je suis un grand fan de SQL, je me demande si d'autres développeurs partageront mon enthousiasme pour jOOQ (ou Linq). Ce type d'approche de l'abstraction de persistance est-il viable? Quels sont les avantages / inconvénients que vous pourriez voir? Comment pourrais-je améliorer jOOQ, et qu'est-ce qui manque à votre avis? Où je me suis trompé, conceptuellement ou pratiquement?

Réponses critiques mais constructives appréciées

Je comprends que le débat est émotionnel. Il existe de nombreux excellents outils qui font déjà des choses similaires. Ce qui m'intéresse, c'est une rétroaction critique mais constructive, basée sur votre propre expérience ou des articles que vous avez pu lire.

Lukas Eder
la source
Gère-t-il les transactions?
Armand
@Alison: Non, il s'agit uniquement de SQL. La gestion des transactions est une entreprise très complexe que je pense que de nombreux autres outils / frameworks (y compris EJB2 / 3) géreront mieux que jOOQ
Lukas Eder
Je suggère fortement un cas d'utilisation très solide et détaillé où vous montrez que votre approche est excellente pour la résoudre.
Notez également que l'édition de CE lourd rendra les réponses plus ou moins inutiles et donc inutilisables pour les futurs lecteurs. Posez plutôt une nouvelle et meilleure question.
Salut Thorbjorn. Vous voulez dire un cas d'utilisation autre que ceux montrés sur la page d'exemples? Ou aimeriez-vous voir des exemples dans la question elle-même? À propos de l'édition: vous avez raison en général. Dans ce cas, cependant, je pensais que les deux réponses que j'ai obtenues jusqu'à présent auraient été quelque peu les mêmes ...
Lukas Eder

Réponses:

5

Je pense que vous êtes sur la bonne voie et que vous devriez continuer avec votre solution. Certaines des critiques précédentes sont trop dures, mais certains arguments valables sont avancés.

Moi aussi, j'ai cherché longtemps et durement une solution ORM complète qui répondrait à mes besoins, mais chaque solution que j'ai examinée est restée courte. Chacun a ses avantages et ses inconvénients, mais aucun n'a vraiment fait tout ce que je voulais. Je suis d'accord avec votre critique de ces solutions - à savoir qu'elles sont généralement complexes et ont une courbe d'apprentissage abrupte.

Le meilleur candidat devrait être la norme de facto, Hibernate. Il est complet, robuste et bien testé. Je le respecte et l'apprécie pour ce que c'est. Maintenant, au risque d'offenser la moitié de la communauté de la programmation, je dois aussi dire que c'est un morceau gonflé et complexe de code non performant. J'ai passé pas mal de temps à fouiller dans ses entrailles, à essayer de le déboguer et à le comprendre, et je n'ai pas été impressionné par ce que j'ai vu. Cela dit, je le recommanderais toujours comme point de départ pour tous ceux qui recherchent un bon ORM. Il excelle dans le simple CRUD, mais je ne l'utiliserais pas pour des requêtes en vrac performantes, telles que l'exploration de données ou le calcul de nombres.

Malheureusement, mon application est plus de la variété de calcul de nombre (bien qu'il y ait aussi du CRUD), j'ai donc décidé de rouler le mien. Je savais dès le départ que ce serait inférieur à la moyenne des autres solutions, mais ce serait assez bon et me donnerait les performances dont j'avais besoin. Maintenant, voici la partie vraiment géniale: cela ressemble beaucoup à votre solution!

C'est ce que je pense que vous avez le plus bien fait: vous avez déclaré vos croyances sous-jacentes comme une sorte d'énoncé de mission, et ces croyances sont correctes. J'ai évidemment passé beaucoup de temps à réfléchir à ce problème aussi, et il est difficile à résoudre. Mais avec le temps, je pense que la communauté de la programmation en vient à mieux le comprendre et nous allons créer de meilleures solutions. Bravo à tous les efforts précédents (en particulier Hibernate), mais je pense que nous pouvons faire mieux.

Votre solution affine mieux le problème, mais elle n'en résout qu'une partie. Je pense qu'une approche en couches peut nous donner tout ce que nous voulons. Ce que vous avez trouvé avec / IMO, c'est la couche de base. Comme vous l'avez suggéré, je pense que cette couche est mieux générée automatiquement sur la base d'un schéma de base de données. Ce devrait être un modèle objet relationnel très simple qui mappe directement sur la base de données et pas plus. Vous avez raison de dire que les données persistent beaucoup plus longtemps que le code, donc à ce niveau, les données devraient conduire le code et non l'inverse. Il prendrait en charge CRUD ainsi que les requêtes en masse performantes. J'implémenterais probablement une sorte de cache L1 sur cette couche.

Cependant, ce qui excelle dans les autres solutions ORM, c'est la possibilité de définir vos objets d'une manière qui ne dépend pas tellement de la structure réelle de la base de données sous-jacente. Pour cette fonctionnalité, je créerais une autre couche. Par nécessité, cette couche devient plus abstraite, espérons-le plus simple (au détriment des fonctionnalités perdues), et s'appuie sur la couche précédente. Il peut utiliser un cache L2.

Je suis prêt à avoir plus de couches, mais le point clé pour moi est qu'en fournissant plusieurs points d'entrée dans la bibliothèque, vous pouvez répondre à tous les besoins. Pour ceux qui veulent une solution CRUD simple qui mappe directement aux objets de leur choix, ils peuvent construire sur la couche supérieure. Pour ceux qui recherchent quelque chose de plus puissant et de plus performant mais qui souhaitent encourir la complexité supplémentaire, ils peuvent se connecter à la couche inférieure. Je ne créerais pas un langage de requête spécial, mais exposerais à la place votre objet de générateur de requête à cette fin. Et puisque le code est en couches, cette fonctionnalité existe naturellement sans pass-through spécial.

Je pense que vous avez une compréhension de l'espace et que vous ne réinventez pas la roue, mais que vous avez plutôt atteint un créneau légèrement différent. Et franchement, c'est une roue qui pourrait de toute façon être améliorée. Vous faites face à une bataille difficile contre les puissances du passé, mais si votre solution est bonne, et je pense que c'est dans cette direction, elle gagnera en popularité en soi.

Dale Anderson
la source
Salut Dale, merci pour tes encouragements! J'aime votre formulation sur les couches et jOOQ étant sur la couche la plus basse avec une abstraction supplémentaire possible sur jOOQ. C'est quelque chose que je veux aborder lorsque j'ai suffisamment d'élan avec jOOQ. L'interfaçage avec JPA et / ou Hibernate sera clairement sur la feuille de route. Comme vous le dites, ces outils excellent dans la simplicité grâce à l'abstraction et ont de nombreuses fonctionnalités que je ne veux pas dans ma couche: transactions, sessions, caches L2, etc. PS: Votre propre solution est-elle du domaine public? Ça m'intéresserait beaucoup!
Lukas Eder
8

"Il y a beaucoup de balles magiques là-bas, et les développeurs naïfs ne manquent pas."

Aucune infraction, il semble que vous ne compreniez pas déjà complètement ce qui a été fait dans cet espace et que vous réinventez donc certaines roues - l'expérience nous dirait que les roues que vous inventez, bien que soignées et amusantes, ne seront probablement pas aussi bon ou utile comme les roues joliment raffinées déjà disponibles.

quentin-starin
la source
1
Merci pour vos commentaires! Avez-vous jeté un œil plus approfondi sur ma bibliothèque? J'essaie précisément d '«abandonner le O» comme l'appelle votre article. jOOQ veut que les développeurs écrivent du code SQL, pas du code OR-Mapped. J'essaie de réaliser ce que Linq fait pour .NET sans pouvoir réécrire le compilateur Java. Félicitations à Microsoft pour Linq! Et j'ose dire que je ne suis pas naïf, car j'ai créé jOOQ alors que je n'avais pas été satisfait d'EJB 2.0 (il y a pas mal de temps), ni d'Hibernate. Précisément pour les raisons que vous indiquez dans votre article. J'ai essayé ce qui a été fait et cela ne convenait pas à mes besoins.
Lukas Eder
jOOQ souhaite que les développeurs utilisent votre API de type Critères. Ce n'est pas du SQL. C'est une façon de créer du SQL qui en réalité est plus laid et plus compliqué que SQL avec très peu, voire aucun, d'avantages réels. "q.addCompareCondition (TAuthor.YEAR_OF_BIRTH, 1920, Comparator.GREATER);" Je ne vois rien de vraiment différent de tout autre outil de génération de classe par table. Ce qui signifie, comme je l'ai dit, qu'il y a une probabilité presque certaine qu'une meilleure existe déjà. Les champs de chaîne générés par le modèle ne sont même pas proches de ce que les expressions lambda permettent.
quentin-starin
1
C'est un peu difficile pour moi de comprendre la motivation derrière votre réponse / commentaire. Je pense toujours que vous n'avez pas examiné de manière approfondie les exemples que j'ai fournis (vous avez cité le tout premier exemple) et votre comparaison avec des produits concurrents me semble quelque peu vague. Le but de ma question était d'obtenir des commentaires constructifs, et je l'apprécierais. Vous mentionnez «de meilleurs outils» et «expressions lambda». Pourriez-vous s'il vous plaît développer? Comment jOOQ se compare-t-il aux outils que vous avez mentionnés? Comment les expressions lambda sont-elles implémentées dans Java 6 - avant qu'Oracle ne puisse les ajouter à Java 8? Merci encore
Lukas Eder
2

Un scénario qui rendrait ce type d'API bien adapté est lorsque vous avez besoin d'un générateur SQL indépendant de la base de données que la plupart des ORM ne vous permettent pas d'avoir. Une grande situation où j'en ai eu besoin est la génération de rapports. J'ai eu besoin de construire SQL d'une manière orientée objet et d'aller exécuter ce sql sur diverses bases de données pour les tester. Hibernate et les autres ORM sont très dépendants des configurations, limitant ainsi ma construction sql de sorte que je ne peux pas combiner la table où l'association n'existe pas dans les xml. Comme toute association est possible dans le module de rapport que je développe, j'avais recherché quelque chose de différent. Ensuite, je suis tombé sur JOOQ. Cela résout juste mon problème. Je viens d'avoir besoin d'un accès en lecture seule, ne rencontrez jamais de problèmes de débogage douloureux comme en veille prolongée.

Je prévois en fait de développer une manière différente de modéliser les données plutôt que la façon courante de POJO et d'utiliser JOOQ comme l'un des fondements qui est une couche pour construire SQL. Donc, en plus de JOOQ, je prévois de créer un moyen plus flexible de modéliser les données / entités en utilisant HashMaps. Ma conception permettrait d'intégrer plus facilement la conception frontale et backend dans un point d'entrée, bien que j'utiliserais différentes couches pour compléter le cadre, tout comme ce que les commentaires ci-dessus ont dit. JOOQ jouera vraiment un très bon rôle comme dans mon propre projet, il sert de base ou de pilier.

Alors, continuez votre bon travail lukas!

vigne
la source
1

Si je comprends bien votre outil, il mappe les objets directement à un cadre SQL conceptuel plutôt que de mapper des objets qui implémentent une correspondance avec la fonctionnalité SQL (ORM), presque comme une abstraction ORM - pour un meilleur contrôle geek afin que vous puissiez utiliser plus de fonctionnalités SQL Les ORM ne vous donnent généralement pas?

Je ne sais pas quel problème vous essayez de résoudre. Étant donné que votre outil nécessite une connaissance approfondie de SQL, les gens n'utiliseraient-ils pas simplement SQL? Est-ce le code de colle dont vous essayez de vous débarrasser? Une meilleure validation des requêtes SQL via la modélisation API au lieu de simples chaînes?

Je dois admettre que vos exemples JOOQ ressemblent à des versions LISP du SQL. Ce n'est pas une mauvaise chose :) et je vois que certaines des choses avancées sont intéressantes, mais les avantages que vous énumérez disparaissent lentement à mesure que vous devenez de plus en plus avancé (plus de config, moins abstrait, plus ancré dans le sanctuaire intérieur du SQL spécifique) moteur, etc.)

Une suggestion que j'aimerais voir manquer dans la plupart des ORM est un cadre qui peut traiter les objets de manière non relationnelle, traduisant les interactions d'objet en quel que soit le backend (SQL, NoSQL, Topic Maps, RDF, etc. .) qui nécessite la mise en cache du modèle utilisé plutôt que des spécificités des interactions SQL, des dialectes et de la pensée relationnelle.

À mon humble avis, bien sûr. :)

AlexanderJohannesen
la source
Salut, merci pour vos commentaires. Vous avez bien compris. Comme le dit qstarin, j'essaie de supprimer le "O" de l'ORM et de rester relationnel. Pourquoi pas du SQL simple? Vous voulez dire JDBC? Avez-vous déjà interrogé votre base de données avec 5 sélections imbriquées et plusieurs jointures, fonctions analytiques avec JDBC? Erreurs de syntaxe, incompatibilité de liaison, etc. Malheureusement, jOOQ ne peut pas être le bon outil pour vous, car il n'y a aucune possibilité de mapper N'IMPORTE QUEL modèle aux objets. Et je ne veux pas ça. jOOQ DEVRAIT être relationnel. Pour les développeurs qui préfèrent cette façon de penser. Pour l'autre, je recommande JPA .. Ou Linq si vous faites .NET
Lukas Eder