Question

La correspondance objet-relationnel a été bien discutée, y compris ici. J'ai de l'expérience avec quelques approches et les pièges et compromis. La vraie résolution semble nécessiter des modifications de l’OA ou des modèles relationnels eux-mêmes.

Si vous utilisez un langage fonctionnel, le même problème se pose-t-il? Il me semble que ces deux paradigmes devraient s’accorder mieux que OO et SGBDR. L’idée de penser en ensembles dans un SGBDR semble s’intégrer au parallélisme automatique que les approches fonctionnelles semblent promettre.

Quelqu'un at-il des opinions ou des idées intéressantes? Quelle est la situation dans l'industrie?

Était-ce utile?

La solution

Les problèmes difficiles liés à l'extension de la base de données relationnelle sont les transactions étendues, les incohérences de types de données, la traduction automatique des requêtes, etc. N + 1 Sélectionnez les problèmes fondamentaux liés à la sortie du système relationnel et, à mon avis, ne changent pas en modifiant le paradigme de la programmation de réception.

Autres conseils

Quel est le but d'un ORM?

L’objet principal d’un ORM est de faire le lien entre le modèle en réseau (orientation d’objet, graphiques, etc.) et le modèle relationnel. Et la principale différence entre les deux modèles est étonnamment simple. Il s’agit de savoir si les parents désignent des enfants (modèle en réseau) ou des enfants, des parents (modèle relationnel).

Avec cette simplicité à l’esprit, je pense il n'existe pas de &" incompatibilité d'impédance & "; entre les deux modèles. Les problèmes que rencontrent généralement les utilisateurs sont purement spécifiques à la mise en oeuvre et devraient pouvoir être résolus s’il existait de meilleurs protocoles de transfert de données entre clients et serveurs.

Comment SQL peut-il résoudre les problèmes rencontrés avec les ORM?

En particulier, le troisième manifeste tente de remédier aux faiblesses du langage SQL et de l'algèbre relationnelle en autorisant les collections imbriquées, qui ont été implémentées dans diverses bases de données, notamment:

  • Oracle (probablement l'implémentation la plus sophistiquée)
  • PostgreSQL (dans une certaine mesure)
  • Informix
  • SQL Server, MySQL, etc. (via " émulation " via XML ou JSON)

À mon avis, si toutes les bases de données implémentaient l'opérateur MULTISET() standard SQL (Oracle, par exemple), les utilisateurs n'utiliseraient plus d'ORM pour le mappage (peut-être encore pour la persistance du graphe d'objets), car ils pourraient matérialiser des collections imbriquées directement à partir de l'intérieur. les bases de données, par exemple cette requête:

SELECT actor_id, first_name, last_name,
  MULTISET (
    SELECT film_id, title
    FROM film AS f
    JOIN film_actor AS fa USING (film_id)
    WHERE fa.actor_id = a.actor_id
  ) AS films
FROM actor AS a

Donnerait tous les acteurs et leurs films comme une collection imbriquée, plutôt que comme un résultat de joint dénormalisé (où les acteurs sont répétés pour chaque film).

Paradigme fonctionnel côté client

La question de savoir si un langage de programmation fonctionnel côté client convient mieux aux interactions de base de données est vraiment orthogonale. Les ORM aident à la persistance des graphiques d’objets. Ainsi, si votre modèle côté client est un graphique et que vous voulez qu’il soit un graphique, vous aurez besoin d’un ORM, que vous manipuliez ce graphique à l’aide d’un langage de programmation fonctionnel.

Cependant, dans la mesure où l'orientation des objets est moins idiomatique dans les langages de programmation fonctionnels, vous avez moins de chances de choisir chaque donnée dans un objet. Pour quelqu'un qui écrit en SQL, projeter des tuples arbitraires est très naturel. SQL embrasse le typage structurel. Chaque requête SQL définit son propre type de ligne sans qu'il soit nécessaire de lui attribuer un nom. Cela convient très bien aux programmeurs fonctionnels, en particulier lorsque l’inférence de type est sophistiquée, au cas où vous ne penseriez jamais à mapper votre résultat SQL sur un objet / une classe précédemment définie.

Un exemple Java utilisant jOOQ de cet article de blog pourrait être:

// Higher order, SQL query producing function:
public static ResultQuery<Record2<String, String>> actors(Function<Actor, Condition> p) {
    return ctx.select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
              .from(ACTOR)
              .where(p.apply(ACTOR)));
}

Cette approche conduit à une composition des instructions SQL bien meilleure que si le langage SQL était résumé par un ORM ou si la chaîne de caractères & naturelle de SQL " la nature ont été utilisés. La fonction ci-dessus peut maintenant être utilisée, par exemple. comme ceci:

// Get only actors whose first name starts with "A"
for (Record rec : actors(a -> a.FIRST_NAME.like("A%")))
    System.out.println(rec);

Abstraction FRM sur SQL

Certains FRM tentent d’abstraire sur le langage SQL, généralement pour les raisons suivantes:

  • Ils prétendent que SQL n’est pas assez composable (jOOQ le nie, c’est très difficile d’obtenir une réponse exacte).
  • Ils affirment que les utilisateurs d'API sont plus habitués à " native " API de collection, par exemple JOIN est traduit en flatMap() et WHERE en filter(), etc.

Pour répondre à votre question

FRM n'est pas & "plus facile &"; que ORM, il résout un problème différent. En fait, FRM ne résout aucun problème, because SQL, étant un langage de programmation déclaratif (qui n’est pas si différent de la programmation fonctionnelle), convient parfaitement aux autres langages de programmation client fonctionnels. Ainsi, un FRM comble simplement le fossé entre SQL, le DSL externe et votre langue client.

(Je travaille pour la société responsable de jOOQ , cette réponse est donc biaisée)

Cela dépend de vos besoins

  1. Si vous souhaitez vous concentrer sur les structures de données, utilisez un ORM tel que JPA / Hibernate
  2. Si vous souhaitez faire la lumière sur les traitements, consultez les bibliothèques FRM: QueryDSL ou Jooq
  3. Si vous devez adapter vos requêtes SQL à des bases de données spécifiques, utilisez JDBC et les requêtes SQL natives.

La force de divers & "Relapping Mapping &"; technologies is is portability: vous vous assurez que votre application s'exécutera sur la plupart des bases de données ACID. Sinon, vous devrez faire face aux différences entre divers dialectes SQL lorsque vous écrivez manuellement les demandes SQL.

Bien sûr, vous pouvez vous limiter au standard SQL92 (puis faire de la programmation fonctionnelle) ou réutiliser des concepts de programmation fonctionnelle avec des frameworks ORM

Les forces ORM sont construites sur un objet de session pouvant servir de goulot d'étranglement:

  1. il gère le cycle de vie des objets tant que la transaction de base de données sous-jacente est en cours d'exécution.
  2. il maintient un mappage individuel entre vos objets java et vos lignes de base de données (et utilise un cache interne pour éviter les objets en double).
  3. il détecte automatiquement les mises à jour des associations et les objets orphelins à supprimer
  4. il gère les problèmes simultanés liés au verrouillage optimiste ou pessimiste.

Néanmoins, ses forces sont aussi ses faiblesses:

  1. La session doit pouvoir comparer des objets, vous devez donc implémenter les méthodes equals / hashCode. Mais l'égalité des objets doit être basée sur & Quot; Business Keys & Quot; et non l'ID de la base de données (les nouveaux objets transitoires n'ont pas d'ID de base de données!). Cependant, certains concepts réifiés n’ont pas d’égalité commerciale (une opération par exemple). Une solution de contournement courante repose sur des GUID qui tendent à gêner les administrateurs de base de données.

  2. La session doit espionner que la relation change, mais ses règles de mappage poussent l'utilisation de collections inappropriées pour les algorithmes métier. Parfois, vous souhaitez utiliser une carte de hachage, mais l'ORM exige que la clé soit un autre & "Objet de domaine enrichi &"; au lieu d'un autre léger ... Ensuite, vous devez implémenter l'égalité d'objet sur l'objet de domaine riche agissant en tant que clé ... Mais vous ne pouvez pas parce que cet objet n'a pas d'équivalent dans le monde des affaires. Vous vous retrouvez donc dans une liste simple sur laquelle vous devez effectuer une itération (d'où résultent des problèmes de performances).

  3. Les API ORM sont parfois inappropriées pour une utilisation réelle. Par exemple, les applications Web du monde réel tentent de renforcer l'isolation de session en ajoutant des & "WHERE &"; clauses quand vous récupérez des données ... Ensuite, le & Quot; Session.get (id) & Quot; ne suffit pas et vous devez vous tourner vers un DSL plus complexe (HSQL, Criteria API) ou revenir au SQL natif

  4. Les objets de base de données sont en conflit avec d'autres objets dédiés à d'autres frameworks (tels que les frameworks OXM = Object / XML Mapping). Par exemple, si vos services REST utilisent la bibliothèque jackson pour sérialiser un objet métier. Mais ce Jackson correspond exactement à un Hibernate One. Ensuite, soit vous fusionnez les deux et un couplage fort entre votre API et votre base de données apparaît Ou vous devez implémenter une traduction et tout le code que vous avez enregistré à partir de l'ORM est perdu là-bas ...

De l'autre côté, FRM est un compromis entre & "Object Mapping relationnel &"; (ORM) et requêtes SQL natives (avec JDBC)

La meilleure façon d'expliquer les différences entre FRM et ORM consiste à adopter une approche DDD.

  • La cartographie relationnelle des objets autorise l'utilisation de " objet de domaine enrichi " qui sont des classes Java dont les états sont mutables lors de la transaction de base de données
  • La cartographie relationnelle fonctionnelle repose sur " objets de domaine médiocre " qui sont immuables (vous devez donc en cloner un nouveau chaque fois que vous souhaitez en modifier le contenu)

Il libère les contraintes imposées à la session ORM et s’appuie le plus souvent sur un DSLle SQL (donc la portabilité n'a pas d'importance) Mais d’autre part, vous devez examiner les détails de la transaction, les problèmes de simultanéité

List<Person> persons = queryFactory.selectFrom(person)
  .where(
    person.firstName.eq("John"),
    person.lastName.eq("Doe"))
  .fetch();

J'imagine que le mappage relationnel fonctionnel devrait être plus facile à créer et à utiliser que OO to SGBDR. Tant que vous interrogez uniquement la base de données, c'est-à-dire. Je ne vois pas (encore) vraiment comment vous pourriez faire des mises à jour de base de données sans effets secondaires de manière agréable.

Le principal problème que je vois est la performance. Aujourd'hui, les RDMS ne sont pas conçus pour être utilisés avec des requêtes fonctionnelles et se comporteront probablement mal dans de nombreux cas.

Je n'ai pas fait de mappage fonctionnel-relationnel, en soi , mais j'ai utilisé des techniques de programmation fonctionnelle pour accélérer l'accès à un SGBDR.

Il est assez courant de commencer avec un jeu de données, d'effectuer des calculs complexes et de stocker les résultats, où les résultats sont un sous-ensemble de l'original avec des valeurs supplémentaires, par exemple. L’approche impérative vous oblige à stocker votre jeu de données initial avec des colonnes NULL supplémentaires, à effectuer votre calcul, puis à mettre à jour les enregistrements avec les valeurs calculées.

semble raisonnable. Mais le problème, c'est que cela peut être très lent. Si votre calcul nécessite une autre instruction SQL en plus de la requête de mise à jour elle-même, ou même doit être effectué dans le code de l'application, vous devez (re) rechercher les enregistrements que vous modifiez après le calcul pour stocker vos résultats dans les bonnes lignes. .

Vous pouvez contourner ce problème en créant simplement un nouveau tableau de résultats. De cette façon, vous pouvez simplement toujours insérer au lieu de mettre à jour. Vous finissez par avoir une autre table, en dupliquant les clés, mais vous n'avez plus besoin de perdre de l'espace sur les colonnes contenant NULL & # 8211; vous ne stockez que ce que vous avez. Vous rejoignez ensuite vos résultats dans votre sélection finale.

I (ab) a utilisé un SGBDR de cette façon et a fini par écrire des instructions SQL qui ressemblaient beaucoup à ceci ...

create table temp_foo_1 as select ...;
create table temp_foo_2 as select ...;
...
create table foo_results as
  select * from temp_foo_n inner join temp_foo_1 ... inner join temp_foo_2 ...;

Il s’agit essentiellement de créer un ensemble de liaisons immuables. La bonne chose, cependant, est que vous pouvez travailler sur des ensembles entiers à la fois. Cela vous rappelle des langages qui vous permettent de travailler avec des matrices, comme Matlab.

J'imagine que cela permettrait également un parallélisme beaucoup plus facile.

Un avantage supplémentaire est que les types de colonnes pour les tables créées de cette manière ne doivent pas être spécifiés car ils sont déduits des colonnes à partir desquelles ils ont été sélectionnés.

Je pense que, comme Sam l’a mentionné, si la base de données devait être mise à jour, il faudrait faire face aux mêmes problèmes de concurrence que dans le monde OO. La nature fonctionnelle du programme pourrait peut-être même être un peu plus problématique que la nature de l'objet en raison de l'état des données, des transactions, etc. du SGBDR.

Mais pour la lecture, le langage fonctionnel pourrait être plus naturel avec certains domaines problématiques (comme il semble l'être indépendamment de la base de données)

Le mappage fonctionnel &; - > SGBDR ne devrait pas avoir de grandes différences avec OO < - > mappages RDMBS. Mais je pense que cela dépend beaucoup du type de type de données que vous souhaitez utiliser, si vous souhaitez développer un programme avec un tout nouveau schéma de base de données ou faire quelque chose contre un schéma de base de données hérité, etc.

Les recherches paresseuses, etc. pour les associations, par exemple, pourraient probablement être très bien implémentées avec certains concepts paresseux liés à l’évaluation. (Même s’ils peuvent très bien se faire avec OO également)

Modifier: avec Google, j'ai trouvé HaskellDB (bibliothèque SQL Haskell) - cela pourrait valoir la peine d'essayer?

Les bases de données et la programmation fonctionnelle peuvent être fusionnées.

par exemple:

Clojure est un langage de programmation fonctionnel basé sur la théorie des bases de données relationnelles.

               Clojure -> DBMS, Super Foxpro
                   STM -> Transaction,MVCC
Persistent Collections -> db, table, col
              hash-map -> indexed data
                 Watch -> trigger, log
                  Spec -> constraint
              Core API -> SQL, Built-in function
              function -> Stored Procedure
             Meta Data -> System Table

Remarque: dans la dernière spéc2, spéc est plus proche de RMDB. voir: wiki spec-alpha2: Schema-and-select

Je préconise: la création d'un modèle de données relationnel en plus de la table de hachage afin de combiner les avantages de NoSQL et de la BDMD. C’est en fait une implémentation inverse de posgtresql.

Duck Typing: Si cela ressemble à un canard et que les charlatans ressemblent à un canard, ce doit être un canard.

Si le modèle de données de clojure ressemble à une BDMB, les installations de clojure comme une BDMR et la manipulation de données de clojure comme une BDMD, clojure doit être une BDMD.

Clojure est un langage de programmation fonctionnel basé sur une base de données basée sur la base de données de base de données

Tout est RMDB

Implémenter un modèle de données relationnel et une programmation basés sur une carte de hachage (NoSQL) )

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top