Après avoir utilisé Hibernate sur la plupart de mes projets pendant environ 8 ans, j'ai atterri sur une entreprise qui décourage son utilisation et souhaite que les applications interagissent uniquement avec la base de données via des procédures stockées.
Après avoir fait cela pendant quelques semaines, je n'ai pas pu créer un modèle de domaine riche de l'application que je commence à construire, et l'application ressemble simplement à un script transactionnel (horrible).
Certains des problèmes que j'ai trouvés sont:
- Impossible de naviguer dans le graphique d'objet car les procédures stockées chargent simplement la quantité minimale de données, ce qui signifie que parfois nous avons des objets similaires avec des champs différents. Un exemple est: nous avons une procédure stockée pour récupérer toutes les données d'un client, et une autre pour récupérer les informations de compte ainsi que quelques champs du client.
- Une grande partie de la logique se retrouve dans des classes auxiliaires, de sorte que le code devient plus structuré (avec des entités utilisées comme anciennes structures C).
- Un code d'échafaudage plus ennuyeux, car il n'y a pas de cadre qui extrait les jeux de résultats d'une procédure stockée et les place dans une entité.
Mes questions sont:
- quelqu'un a-t-il été dans une situation similaire et n'était pas d'accord avec l'approche de la procédure de magasin? Qu'est-ce que tu as fait?
- Y a-t-il un réel avantage à utiliser des procédures stockées? à part le point idiot de "personne ne peut publier une table de baisse".
- Existe-t-il un moyen de créer un domaine riche à l'aide de procédures stockées? Je sais qu'il est possible d'utiliser AOP pour injecter des DAO / référentiels dans des entités afin de pouvoir naviguer dans le graphique d'objet. Je n'aime pas cette option car elle est très proche du vaudou.
Conclusion
Tout d'abord, merci à tous pour vos réponses. La conclusion que je suis arrivée est que les ORM ne permettent pas la création de modèles de domaine riche (comme certaines personnes l'ont mentionné), mais cela simplifie la quantité de travail (souvent répétitif). Ce qui suit est une explication plus détaillée de la conclusion, mais n'est basé sur aucune donnée solide.
La plupart des applications demandent et envoient des informations à d'autres systèmes. Pour ce faire, nous créons une abstraction dans les termes du modèle (par exemple, un événement commercial) et le modèle de domaine envoie ou reçoit l'événement. L'événement a généralement besoin d'un petit sous-ensemble d'informations du modèle, mais pas de l'ensemble du modèle. Par exemple, dans une boutique en ligne, une passerelle de paiement demande des informations sur l'utilisateur et le total pour facturer un utilisateur, mais ne nécessite pas l'historique des achats, les produits disponibles et toute la base de clients. L'événement a donc un petit ensemble de données spécifiques.
Si nous prenons la base de données d'une application comme un système externe, nous devons créer une abstraction qui nous permet de mapper les entités du modèle de domaine à la base de données ( comme l'a mentionné NimChimpsky , en utilisant un mappeur de données). La différence évidente est que nous devons maintenant créer à la main un mappage pour chaque entité de modèle avec la base de données (un schéma hérité ou des procédures stockées), avec la douleur supplémentaire que, puisque les deux ne sont pas synchronisés, une entité de domaine peut mapper partiellement à une entité de base de données (par exemple, une classe UserCredentials qui ne contient que le nom d'utilisateur et le mot de passe est mappée à une table Users qui a d'autres colonnes), ou une entité de modèle de domaine peut mapper vers plusieurs entités de base de données (par exemple, s'il y a un à un un mappage sur la table, mais nous voulons toutes les données dans une seule classe).
Dans une application avec quelques entités, la quantité de travail supplémentaire peut être petite s'il n'y a pas besoin de traverser les entités, mais elle augmente quand il y a un besoin conditionnel de traverser les entités (et donc nous pourrions vouloir implémenter une sorte de `` paresseux '' chargement'). Au fur et à mesure qu'une application grandit pour avoir plus d'entités, ce travail augmente simplement (et j'ai l'impression qu'il augmente de façon non linéaire). Mon hypothèse ici, est que nous n'essayons pas de réinventer un ORM.
L'un des avantages du traitement de la base de données comme un système externe est que nous pouvons coder les situations dans lesquelles nous voulons que 2 versions différentes d'une application s'exécutent, dans lesquelles chaque application a un mappage différent. Cela devient plus intéressant dans le scénario de livraisons continues à la production ... mais je pense que c'est aussi possible avec des ORM dans une moindre mesure.
Je vais rejeter l'aspect sécurité, au motif qu'un développeur, même s'il n'a pas accès à la base de données, peut obtenir la plupart sinon la totalité des informations stockées dans un système, simplement en injectant du code malveillant (par exemple. Je ne peux pas croire que j'ai oublié de supprimer la ligne qui enregistre les détails de la carte de crédit des clients, cher seigneur! ).
Petite mise à jour (6/6/2012)
Les procédures stockées (au moins dans Oracle) empêchent de faire quelque chose comme la livraison continue avec zéro temps d'arrêt, car toute modification de la structure des tables invalidera les procédures et les déclencheurs. Ainsi, pendant la mise à jour de la base de données, l'application sera également arrêtée. Oracle fournit une solution pour cette redéfinition basée sur l'édition , mais les quelques administrateurs de base de données que j'ai interrogés sur cette fonctionnalité ont mentionné qu'elle était mal implémentée et qu'ils ne la mettraient pas dans une base de données de production.
Réponses:
Votre application doit toujours être modélisée à partir des principes de conception pilotés par domaine. Que vous utilisiez un ORM, un JDBC droit, appeler des SP (ou autre) ne devrait pas avoir d'importance . Espérons qu'une couche mince faisant abstraction de votre modèle à partir des SP devrait faire l'affaire dans ce cas. Comme l'a indiqué une autre affiche , vous devez afficher les SP et leurs résultats en tant que service et mapper les résultats sur votre modèle de domaine.
la source
Dans le monde financier (et dans les endroits où la conformité Sarbanes-Oxley est requise), vous devez être en mesure d'auditer les systèmes pour vous assurer qu'ils font ce qu'ils sont censés faire. Dans ces cas, il est beaucoup plus facile de garantir la conformité lorsque tous les accès aux données se font via des procédures stockées. Et lorsque tout SQL ad-hoc est supprimé, il est beaucoup plus difficile de masquer les choses. Pour un exemple de la raison pour laquelle ce serait une «bonne chose», je vous renvoie au document classique de Ken Thompson, Reflections on Trusting Trust .
la source
Les procédures stockées sont beaucoup plus efficaces que le code SQL côté client. Ils précompilent SQL dans la base de données, ce qui lui permet également d'effectuer certaines optimisations.
Sur le plan architectural, un SP renvoie les données minimales requises pour une tâche, ce qui est bon car cela signifie que moins de données sont transférées. Si vous avez une telle architecture, vous devez considérer la base de données comme un service (pensez-y comme un service Web et chaque SP est une méthode à appeler). Travailler avec cela ne devrait pas être un problème, alors qu'un ORM vous guide dans l'utilisation de données distantes comme si elles étaient locales, vous incitant ainsi à introduire des problèmes de performances si vous n'y faites pas attention.
J'ai été dans des situations où nous avons utilisé complètement les SP, la base de données a fourni une API de données et nous l'avons utilisée. Cette application particulière était à très grande échelle et fonctionnait incroyablement bien. Je n'aurai plus rien de mal à dire sur les SP après ça!
Il y a un autre avantage: les administrateurs de bases de données écriront toutes vos requêtes SQL pour vous et gèreront avec plaisir toute la hiérarchie relationnelle dans la base de données, vous n'avez donc pas à le faire.
la source
the approach of letting the DBAs write the procedures smells like development silos
+100 internets à vous pour ce joyau de vérité. J'ai toujours vu cela comme le cas où l'accès aux données était contrôlé par des procédures stockées.Ce qui arrive souvent, c'est que les développeurs utilisent incorrectement leurs objets ORM comme modèles de domaine.
Ceci est incorrect et lie votre domaine directement à votre schéma de base de données.
Ce qui devrait vraiment être, c'est des modèles de domaine séparés aussi riches que vous le souhaitez et utilisez la couche ORM séparément.
Cela signifie que vous devrez mapper entre chaque ensemble d'objets.
la source
Vos objets de domaine peuvent être remplis à votre guise, il n'est pas nécessaire d'utiliser Hibernate. Je pense que le terme approprié est mappeur de données . Il est très possible que vos données persistantes aient une structure complètement différente de vos objets de domaine.
la source