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.
Réponses:
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.
la source
"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.
la source
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!
la source
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. :)
la source