277 votes

Utiliser un ORM ou du SQL pur ?

Pour certaines des applications que j'ai développées (puis oubliées), j'ai écrit du SQL simple, principalement pour MySQL. Bien que j'aie utilisé des ORM en python comme SQLAlchemy je ne suis pas resté longtemps avec eux. En général, c'était soit la documentation, soit la complexité (de mon point de vue) qui me retenait.

Je vois les choses comme suit : utiliser un ORM pour la portabilité, utiliser du SQL pur si l'on ne veut utiliser qu'un seul type de base de données. Je cherche vraiment des conseils pour savoir quand utiliser un ORM ou SQL lors du développement d'une application qui nécessite un support de base de données.

En y réfléchissant, il serait de loin préférable d'utiliser un wrapper léger pour gérer les incohérences de la base de données plutôt que d'utiliser un ORM.

1 votes

Normalisation, sécurité, maintenabilité, abstraction du langage, DRY, etc.

0 votes

Les performances avec ORM peuvent être proches de SQL, tout dépend si vous l'utilisez correctement et avec les bons paramètres... Voir comment rendre EF6.x 5 fois plus rapide : linkedin.com/pulse/

0 votes

Pour l'architecture ORM et le mode d'emploi (ce qu'il faut éviter), voici mon autre lien : linkedin.com/pulse/

278voto

cletus Points 276888

En tant que personne ayant passé pas mal de temps à travailler avec JPA (Java Persistence API, essentiellement l'API ORM standardisée pour Java/J2EE/EJB), qui comprend Hibernate, EclipseLink, Toplink, OpenJPA et d'autres, je vais partager certaines de mes observations.

  1. Les ORM ne sont pas rapides. Ils peuvent être adéquats et, la plupart du temps, adéquats c'est bien, mais dans un environnement à haut volume et faible latence, ils sont à proscrire ;
  2. Dans les langages de programmation à usage général comme Java et C#, il faut beaucoup de magie pour qu'ils fonctionnent (par exemple, le tissage en temps de charge en Java, l'instrumentation, etc ;)
  3. Lorsque vous utilisez un ORM, plutôt que de vous éloigner de SQL (ce qui semble être le but recherché), vous serez surpris du temps que vous passez à modifier le XML et/ou les annotations/attributs pour que votre ORM génère un SQL performant ;
  4. Pour les requêtes complexes, il n'y a vraiment aucun substitut. Par exemple, dans JPA, il y a des requêtes qui ne sont tout simplement pas possibles en SQL brut et lorsque vous devez utiliser du SQL brut dans JPA, ce n'est pas joli (C#/.Net a au moins des types dynamiques -var - qui sont beaucoup plus agréables qu'un tableau d'objets) ;
  5. L'utilisation des ORM donne lieu à un grand nombre d'écueils. Il s'agit notamment de comportements involontaires ou inattendus, du fait que vous devez intégrer la capacité d'effectuer des mises à jour SQL de votre base de données (en utilisant refresh() dans JPA ou des méthodes similaires, car JPA met tout en cache par défaut afin de ne pas attraper une mise à jour directe de la base de données ;)
  6. L'inadéquation objet-relationnel va toujours poser des problèmes. Pour tout problème de ce type, il faut trouver un compromis entre la complexité et la complétude de l'abstraction. Parfois, j'ai eu l'impression que JPA allait trop loin et se heurtait à une véritable loi des rendements décroissants, où la complexité n'était pas justifiée par l'abstraction.

Il y a un autre problème qui nécessite un peu plus d'explications.

Le modèle traditionnel d'une application Web consiste à disposer d'une couche de persistance et d'une couche de présentation (avec éventuellement des services ou d'autres couches intermédiaires, mais ce sont les deux principales pour cette discussion). Les ORM forcent une vue rigide de votre couche de persistance jusqu'à la couche de présentation (c'est-à-dire vos entités).

L'une des critiques des méthodes SQL plus brutes est que l'on se retrouve avec tous ces VO (objets de valeur) ou DTO (objets de transfert de données) qui sont utilisés par une seule requête. Cette situation est présentée comme un avantage des ORM, car elle permet de s'en débarrasser.

Le problème est que ces problèmes ne disparaissent pas avec les ORM, ils se déplacent simplement vers la couche de présentation. Au lieu de créer des VOs/DTOs pour les requêtes, vous créez des objets de présentation personnalisés, généralement un pour chaque vue. En quoi est-ce mieux ? IMHO, ça ne l'est pas.

J'ai écrit à ce sujet dans ORM ou SQL : Sommes-nous déjà arrivés ? .

Ma technologie de persistance de prédilection (en Java) est aujourd'hui ibatis. C'est une enveloppe assez fine autour de SQL qui fait plus de 90% de ce que JPA peut faire (il peut même faire du chargement paresseux de relations bien que ce ne soit pas bien documenté) mais avec beaucoup moins de frais généraux (en termes de complexité et de code réel).

Cela s'est produit l'année dernière dans une application GWT que j'écrivais. Beaucoup de traduction d'EclipseLink vers des objets de présentation dans l'implémentation du service. Si nous utilisions ibatis, il aurait été beaucoup plus simple de créer les objets appropriés avec ibatis, puis de les passer de haut en bas de la pile. Certains puristes pourraient dire que c'est Bad™. Peut-être bien (en théorie) mais je vais vous dire : cela aurait conduit à un code plus simple, une pile plus simple et plus de productivité.

2 votes

J'ai eu l'idée de poster une autre question (bien qu'elle ait fait l'objet d'un wiki communautaire), juste pour rassembler des ressources sur ce genre de choses. Concernant le dernier paragraphe : J'aime la simplicité. Probablement trop.

0 votes

Je suis généralement d'accord avec ce que vous dites, mais je ne suis pas sûr que vous ayez entièrement raison sur le point 5). Par défaut, JPA ne met pas tout en cache pour toujours. Il ne met en cache des choses que pendant le contexte de persistance, qui, dans de nombreux cas, est lié à une transaction. Pendant une transaction, vous ne voyez pas non plus les mises à jour effectuées dans une autre transaction en SQL brut (en fonction de votre niveau d'isolation). Par conséquent, le cache l1 de JPA n'est généralement pas un problème. Lorsque vous utilisez un contexte de persistance étendu ou un cache l2, vous pouvez manquer des mises à jour externes, mais ces deux éléments ne sont pas proposés par défaut dans JPA.

0 votes

Arjan, oui le cache l2 n'est pas activé par défaut. Mais vous l'activerez presque toujours. JPA sans l2 est très lent et la base de données agressive. Donc, dans la plupart des cas, l2 est activé. Dans les systèmes d'entreprise, vous avez probablement aussi d'autres sources qui peuvent modifier les enregistrements dans la base de données, et c'est vraiment un problème.

191voto

Cameron Pope Points 3375

Les ORM ont des fonctionnalités intéressantes. Ils peuvent s'occuper d'une grande partie du travail de copie des colonnes de la base de données vers les champs de l'objet. Ils gèrent généralement la conversion des types de date et d'heure du langage vers le type de base de données approprié. Ils gèrent généralement les relations un à plusieurs de manière assez élégante en instanciant des objets imbriqués. J'ai constaté que si vous concevez votre base de données en gardant à l'esprit les forces et les faiblesses de l'ORM, vous économiserez beaucoup de travail pour entrer et sortir les données de la base. (Vous voudrez savoir comment il gère le polymorphisme et les relations plusieurs à plusieurs si vous avez besoin de les mapper. Ce sont ces deux domaines qui fournissent la plupart des "impedance mismatch" qui font que certains appellent ORM le "vietnam de l'informatique").

Pour les applications qui sont transactionnelles, c'est-à-dire que vous faites une demande, obtenez des objets, les traversez pour obtenir des données et les rendre sur une page Web, l'impact sur les performances est faible et, dans de nombreux cas, l'ORM peut être plus rapide parce qu'il met en cache des objets qu'il a déjà vus et qui, autrement, auraient interrogé la base de données plusieurs fois.

Pour les applications qui produisent beaucoup de rapports, ou qui traitent un grand nombre de lignes de base de données par requête, la taxe ORM est beaucoup plus lourde, et la mise en cache qu'elles effectuent se transforme en une grosse charge inutile qui accapare la mémoire. Dans ce cas, un simple mappage SQL (LinQ ou iBatis) ou des requêtes SQL codées à la main dans un DAL léger sont la solution.

J'ai constaté que pour toute application à grande échelle, vous serez amené à utiliser les deux approches. (ORM pour le CRUD simple et SQL/thin DAL pour le reporting).

0 votes

Pourriez-vous définir l'expression "grand nombre de lignes de la base de données par demande" ? S'il vous plaît :)

0 votes

Puis-je donc intégrer JPA à IBatis par exemple ? Et les faire fonctionner dans la même transaction ?

3 votes

Une autre considération dont personne ne semble discuter est la gestion de base des états. Toute cette pile de frameworks (JSF, JPA, etc.) est basée sur les méthodes get/set des Java beans. Il s'agit d'une TONNE de texte passe-partout pour chaque table, pour chaque colonne et ... voici le véritable anti-modèle : Exposer chaque champ comme s'il était public. En effet, avoir une méthode get/set sur les champs d'un objet/table/rangée est très proche de la violation de tous les principes de masquage de l'information et d'encapsulation. Enfin, pour en revenir à la gestion des états... où est l'option d'immuabilité ? Peut-on ou doit-on autoriser les objets à moitié définis ? Aucune option dans la plupart des cas.

56voto

Max Toro Points 13050

Je dis SQL simple pour R eads, ORM pour CUD .

Les performances sont un sujet qui me préoccupe toujours, surtout dans les applications web, mais aussi la maintenabilité et la lisibilité du code. Pour résoudre ces problèmes, j'ai écrit SqlBuilder .

2 votes

Qu'est-ce que la CUD ? Je n'arrive pas à trouver la définition.

41 votes

@KimchiMan CRUD sans le R.

7 votes

CUD - Créer, mettre à jour, supprimer.

14voto

Anton Gogolev Points 59794

ORM n'est pas seulement la portabilité (qui est assez difficile à atteindre même avec ORM, d'ailleurs). Ce qu'il vous donne est essentiellement une couche d'abstraction sur un magasin persistant, quand un outil ORM vous libère de l'écriture de requêtes SQL passe-partout (sélections par PK ou par prédicats, insertions, mises à jour et suppressions) et vous permet de vous concentrer sur le domaine problématique.

3 votes

Je pensais à quelque chose de plus proche de la portabilité à travers les saveurs des bases de données. Je ne devrais pas poster de questions tard dans la nuit.

1 votes

C'est exactement ce que je disais : même les scénarios les plus basiques peuvent potentiellement être sujets à des erreurs dans différents SGBD - par exemple, une gestion différente des NULLs.

0 votes

Un ORM vous donne une couche d'abstraction sur les relations entre les objets, mais il n'y a pas de grand avantage en ce qui concerne les requêtes passe-partout que vous mentionnez. Dans une application JDBC, vous pouvez écrire ces types de requêtes avec une petite quantité de code dans une superclasse abstraite ou une classe utilitaire. Il n'est pas nécessaire de répéter le modèle pour chaque nouvelle table.

12voto

le dorfier Points 27267

Toute conception respectable nécessitera une certaine abstraction pour la base de données, juste pour gérer le décalage d'impédance. Mais la première étape la plus simple (et adéquate pour la plupart des cas) serait un DAL, pas un ORM lourd. Vos seules options ne sont pas celles qui se trouvent aux extrémités du spectre.


EDIT en réponse à un commentaire me demandant de décrire comment je distingue DAL de ORM :

Un DAL est ce que vous écrivez vous-même, en commençant peut-être par une classe qui encapsule simplement une table et fait correspondre ses champs aux propriétés. Un ORM est le code que vous n'écrivez pas pour les mécanismes d'abstraction déduits d'autres propriétés de votre schéma de base de données, principalement les PK et les FK. (C'est là que vous découvrez si les abstractions automatiques commencent à devenir fuyantes ou non. Je préfère les informer intentionnellement, mais ce n'est peut-être que ma préférence personnelle).

2 votes

Où se situe la limite entre ce qui est un DAL et ce qui est un ORM ?

6 votes

Donc, si vous êtes l'auteur d'un ORM, votre ORM se transforme automatiquement en DAL ? :)

0 votes

DAL = couche de persistance et ORM est un outil que vous utilisez dans votre DAL pour effectuer des opérations CRUD dans le magasin de données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X