Frage

Die Objektrelationskartierung wurde gut diskutiert, auch hier. Ich habe Erfahrung mit ein paar Ansätzen und den Fallstricken und Kompromissen. Die wahre Lösung scheint Änderungen an den OO- oder Relationalmodellen selbst zu erfordern.

Wenn sich das gleiche Problem bei Verwendung einer funktionalen Sprache verwenden? Es scheint mir, dass diese beiden Paradigmen besser zusammenpassen sollten als OO und RDBMs. Die Idee des Denkens in Sets in einem RDBMS scheint mit der automatischen Parallelität zu passen, die funktionelle Ansätze zu versprechen scheinen.

Hat jemand interessante Meinungen oder Erkenntnisse? Wie ist der Stand des Spiels in der Branche?

War es hilfreich?

Lösung

Die schwierigen Probleme bei der Erweiterung der relationalen Datenbank sind erweiterte Transaktionen, Datentyp-Fehlpaarungen, automatisierte Abfragetranslation und Dinge wie N+1 auswählen Das sind grundlegende Probleme beim Verlassen des relationalen Systems und ändern sich meiner Meinung nach nicht, indem sie das empfangende Programmierparadigma ändern.

Andere Tipps

Was ist der Zweck eines Orms?

Der Hauptzweck der Verwendung eines ORM besteht darin, zwischen dem vernetzten Modell (Objektorientierung, Diagramme usw.) und dem relationalen Modell zu überbrücken. Und der Hauptunterschied zwischen den beiden Modellen ist überraschend einfach. Es ist, ob Eltern auf Kinder (vernetzte Modell) oder Kinder auf Eltern (relationales Modell) verweisen.

Mit dieser Einfachheit glaube ich Es gibt keine "Impedanz -Nichtübereinstimmung" zwischen den beiden Modellen. Die Probleme, auf die die Menschen normalerweise begegnet sind, sind nur implementierungsspezifisch und sollten lösbar sein, wenn es bessere Datenübertragungsprotokolle zwischen Clients und Servern gab.

Wie können SQL die Probleme mit Ormen angehen?

Insbesondere die drittes Manifest Versucht, die Mängel der SQL -Sprache und der relationalen Algebra zu beheben, indem verschachtelte Sammlungen ermöglicht werden, die in verschiedenen Datenbanken implementiert wurden, darunter:

  • Oracle (wahrscheinlich die anspruchsvollste Implementierung)
  • PostgreSQL (in gewissem Maße)
  • Informix
  • SQL Server, MySQL usw. (durch "Emulation" über XML oder JSON)

Meiner Meinung nach, wenn alle Datenbanken den SQL -Standard implementiert haben MULTISET() Operator (z. B. Oracle), würden Personen keine Orms mehr zum Zuordnen verwenden (möglicherweise noch für die Persistenz von Objektgraphen), da sie verschachtelte Sammlungen direkt aus den Datenbanken materialisieren könnten, z. B. diese Abfrage:

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

Würde alle Schauspieler und ihre Filme als verschachtelte Sammlung als ein denormalisiertes Join -Ergebnis liefern (wo Schauspieler für jeden Film wiederholt werden).

Funktionales Paradigma auf der Clientseite

Die Frage, ob eine funktionale Programmiersprache auf der Client -Seite besser für Datenbankinteraktionen geeignet ist, ist wirklich orthogonal. ORMs helfen bei der Persistenz von Objektgraphen. Wenn Ihr Client -Seitenmodell also ein Diagramm ist und es sich um ein Diagramm handelt, benötigen Sie ein ORM, unabhängig davon, ob Sie dieses Diagramm mithilfe einer funktionalen Programmiersprache manipulieren.

Da die Objektorientierung jedoch in funktionellen Programmiersprachen weniger idiomatisch ist, ist es weniger wahrscheinlich, dass Sie jedes Datenelement in ein Objekt schieben. Für jemanden, der SQL schreibt, das willkürlich projiziert Tupel ist sehr natürlich. SQL umfasst die strukturelle Typisierung. Jede SQL -Abfrage definiert ihren eigenen Zeilentyp, ohne ihm zuvor einen Namen zuzuweisen. Das ist sehr gut bei funktionalen Programmierern, insbesondere wenn die Typinferenz anspruchsvoll ist, bei dem Sie niemals daran denken, Ihr SQL -Ergebnis zu einem zuvor definierten Objekt / einer zuvor definierten Klasse zuzuordnen.

Ein Beispiel in Java verwendet Jooq Aus diesem Blog -Beitrag könnte sein:

// 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)));
}

Dieser Ansatz führt zu einer viel besseren Kompositionalität von SQL -Anweisungen als wenn die SQL -Sprache von einigen ORM abstrahiert wurde oder wenn die natürliche "String -basierte" Natur von SQL verwendet wurde. Die obige Funktion kann jetzt verwendet werden, zB wie folgt:

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

FRM -Abstraktion über SQL

Einige FRMs versuchen, über die SQL -Sprache zu abstrakt, normalerweise aus diesen Gründen:

  • Sie behaupten, SQL sei nicht komponierbar genug (JOOQ widerlegt dies, es ist nur sehr schwer, richtig zu machen).
  • Sie behaupten, dass API -Benutzer eher an "native" Sammlungs -APIs gewöhnt sind, also z. JOIN wird übersetzt in flatMap() und WHERE wird übersetzt in filter(), etc.

Zur Beantwortung Ihrer Frage

FRM ist nicht "einfacher" als ORM, es löst ein anderes Problem. Tatsächlich löst FRM überhaupt kein Problem, da SQL, eine deklarative Programmiersprache selbst (die sich nicht so von der funktionalen Programmierung unterscheidet), eine sehr gute Übereinstimmung für andere funktionale Client -Programmiersprachen ist. Wenn überhaupt, schließt ein FRM einfach die Lücke zwischen SQL, der externen DSL und Ihrer Kundensprache.

(Ich arbeite für das Unternehmen dahinter Jooq, Also ist diese Antwort voreingenommen)

Das hängt von Ihren Bedürfnissen ab

  1. Wenn Sie sich auf die Datenstrukturen konzentrieren möchten, verwenden Sie einen Orm wie JPA/Hibernate
  2. Wenn Sie die Behandlungen beleuchten möchten, werfen Sie einen Blick auf die Bibliotheken: QueryDSL oder JOOQ
  3. Wenn Sie Ihre SQL -Anfragen auf bestimmte Datenbanken einstellen müssen, verwenden Sie JDBC- und native SQL -Anfragen

Der String der verschiedenen "relationalen Mapping" -Technologien ist die Portabilität: Sie stellen sicher, dass Ihre Anwendung in den meisten Säuredatenbanken ausgeführt wird. Andernfalls werden Sie mit Unterschieden zwischen verschiedenen SQL -Dialekten fertig werden, wenn Sie die SQL -Anfragen manuell schreiben.

Natürlich können Sie sich auf den SQL92 -Standard zurückhalten (und dann einige funktionale Programmierungen durchführen) oder einige Konzepte der Funktionsprogrammierung mit ORM -Frameworks wiederverwenden können

Die Orm -Streenghen werden über ein Sitzungsobjekt gebaut, das als Engpass wirken kann:

  1. Es verwaltet den Lebenszyklus der Objekte, solange die zugrunde liegende Datenbank -Transaktion ausgeführt wird.
  2. Es führt eine Eins-zu-Eins-Zuordnung zwischen Ihren Java-Objekten und Ihren Datenbankzeilen (und verwenden einen internen Cache, um doppelte Objekte zu vermeiden).
  3. Es erkennt automatisch Assoziationsaktualisierungen und die zum Löschen von Orphan -Objekten
  4. Es behandelt gleichzeitige Probleme mit optimistischem oder pessimistischem Schloss.

Trotzdem sind seine Stärken auch seine Schwächen:

  1. Die Sitzung muss in der Lage sein, Objekte zu vergleichen, sodass Sie gleiche Methoden/Hashcode -Methoden implementieren müssen. Die Gleichstellung der Objekte muss jedoch auf "Geschäftsschlüssel" und nicht auf Datenbank -ID verwurzelt sein (neue transiente Objekte haben keine Datenbank -ID!). Einige refizierte Konzepte haben jedoch keine Geschäftsgleichheit (zum Beispiel eine Operation). Eine gemeinsame Problemumgehung beruht auf Richtlinien, die die Datenbankadministratoren tendenziell verärgern.

  2. Die Sitzung muss Änderungen der Beziehung ausspionieren, aber ihre Zuordnungsregeln veranlassen die Verwendung von Sammlungen, die für die Geschäftsalgorithmen nicht geeignet sind. Irgendwann möchten Sie einen HashMap verwenden, aber der ORM erfordert, dass der Schlüssel ein weiteres "reiches Domain -Objekt" anstelle eines anderen Lichts ist ... dann müssen Sie die Objektgleichheit auf dem reichen Domain -Objekt implementieren, das als Schlüssel ... Aber Sie können es nicht, weil dieses Objekt kein Gegenstück in der Geschäftswelt hat. Sie greifen also auf eine einfache Liste zurück, über die Sie iterieren müssen (und Leistungsprobleme resultieren).

  3. Die ORM-API ist manchmal ungeeignet für den Einsatz in der realen Welt. Beispielsweise versuchen reale Webanwendungen mit Real World -Anwendungen, die Isolation der Sitzung durchzusetzen, indem Sie einige "Where" -Anklauseln hinzufügen, wenn Sie Daten abrufen ... dann die "Sitzung (id (id)" aus und Sie müssen sich an komplexere DSL wenden ( HSQL, Kriterien -API) oder kehren Sie zu nativem SQL zurück

  4. Die Datenbankobjekte stehen in Konflikt mit anderen Objekten, die anderen Frameworks gewidmet sind (wie Oxm Frameworks = Object/XML Mapping). Wenn beispielsweise Ihre REST -Dienste Jackson Library verwenden, um ein Geschäftsobjekt zu serialisieren. Aber dieser Jackson ist genau einen Winterschlaf. Dann fusionieren Sie entweder beide und eine starke Kopplung zwischen Ihrer API und Ihrer Datenbank erscheint oder Sie müssen eine Übersetzung implementieren und den gesamten Code, den Sie aus dem ORM gespeichert haben, geht dort verloren ...

Auf der anderen Seite ist FRM ein Kompromiss zwischen "Object Relational Mapping" (ORM) und nativen SQL-Abfragen (mit JDBC)

Der beste Weg, um Unterschiede zwischen FRM und ORM zu erklären, besteht darin, einen DDD -Ansatz anzuwenden.

  • Objekt Relational Mapping ermächtigt die Verwendung von "reichem Domänenobjekt", bei denen es sich um Java -Klassen handelt, deren Zustände während der Datenbanktransaktion veränderlich sind
  • Die funktionale relationale Zuordnung beruht auf "schlechten Domänenobjekten", die unveränderlich sind (so sehr, dass Sie jedes Mal, wenn Sie seinen Inhalt ändern möchten, eine neue klonen müssen)

Es veröffentlicht die Einschränkungen, die in die ORM -Sitzung aufgenommen werden, und stützt sich die meiste Zeit auf einem DSL über die SQL (so dass die Portabilität keine Rolle spielt).

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

Ich würde vermuten, dass funktional für die relationale Zuordnung einfacher zu erstellen und zu verwenden ist als OO zu RDBMs. Solange Sie nur die Datenbank abfragen, das heißt. Ich sehe (noch) nicht wirklich, wie Sie Datenbankaktualisierungen ohne Nebenwirkungen auf gute Weise durchführen können.

Das Hauptproblem, das ich sehe, ist die Leistung. Die heutigen RDMs sind nicht so konzipiert, dass sie mit funktionellen Abfragen verwendet werden können, und verhalten sich wahrscheinlich in einigen Fällen schlecht.

Ich habe nicht funktional-relationale Mapping gemacht, an sich, Aber ich habe funktionelle Programmierechniken verwendet, um den Zugriff auf ein RDBM zu beschleunigen.

Es ist weit verbreitet, mit einem Datensatz zu beginnen, eine komplexe Berechnung durchzuführen und die Ergebnisse zu speichern, wobei die Ergebnisse beispielsweise eine Teilmenge des Originals mit zusätzlichen Werten sind. Der imperative Ansatz schreibt vor, dass Sie Ihren ersten Datensatz mit zusätzlichen Nullspalten speichern, Ihre Berechnung durchführen und die Datensätze mit den berechneten Werten aktualisieren.

Scheint vernünftig. Das Problem dabei ist jedoch, dass es sehr langsam werden kann. Wenn Ihre Berechnung eine weitere SQL-Anweisung neben der Update-Abfrage selbst erfordert oder sogar im Anwendungscode erfolgen muss, müssen Sie buchstäblich nach den Datensätzen suchen, die Sie nach der Berechnung ändern, um Ihre Ergebnisse in den richtigen Zeilen zu speichern .

Sie können dies umgehen, indem Sie einfach eine neue Tabelle für Ergebnisse erstellen. Auf diese Weise können Sie immer immer einfügen, anstatt Aktualisierungen zu erhalten. Am Ende haben Sie einen weiteren Tisch, der die Schlüssel dupliziert, aber Sie müssen keinen Platz mehr für Spalten verschwenden, um Null zu speichern - Sie speichern nur, was Sie haben. Sie beitragen dann Ihren Ergebnissen in Ihrem endgültigen Auswahl.

Ich (AB) habe ein RDBMS auf diese Weise verwendet und schließlich SQL -Anweisungen geschrieben, die meistens so aussahen ...

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 ...;

Was dies im Wesentlichen tut, ist eine Reihe unveränderlicher Bindungen. Das Schöne ist jedoch, dass Sie gleichzeitig an ganzen Sets arbeiten können. Erinnert Sie an Sprachen, mit denen Sie mit Matrizen wie Matlab arbeiten können.

Ich kann mir vorstellen, dass dies auch die Parallelität viel einfacher ermöglichen würde.

Ein zusätzlicher Vorteil ist, dass Arten von Spalten für Tabellen, die auf diese Weise erstellt wurden, nicht angegeben werden müssen, da sie aus den Spalten abgeleitet werden, aus denen sie ausgewählt sind.

Ich würde denken, dass, wie Sam erwähnte, die gleichen Probleme mit der Parallelität wie bei OO World konfrontiert werden müssen, wenn die DB aktualisiert werden sollte. Die funktionale Natur des Programms könnte aufgrund des Datenzustands, Transaktionen usw. der RDBMs möglicherweise sogar ein wenig problematischer sein als die Objekt Natur.

Für das Lesen könnte die funktionale Sprache jedoch mit einigen Problembereichen natürlicher sein (wie sie scheinbar unabhängig von der DB zu sein scheint)

Die funktionale <--> RDBMS-Zuordnung sollte keine großen Unterschiede zu oo <-> rdmbs Mappings haben. Aber ich denke, das hängt sehr davon ab, welche Art von Datentypen Sie verwenden möchten, wenn Sie ein Programm mit einem brandneuen DB -Schema entwickeln oder etwas gegen ein alter DB -Schema usw. tun möchten.

Die faulen Abrufen usw. für Assoziationen könnten beispielsweise wahrscheinlich mit einigen faulen Bewertungskonzepten ziemlich gut implementiert werden. (Auch wenn sie auch mit OO gut gemacht werden können)

Bearbeiten: Mit etwas Googling habe ich gefunden Haskelldb (SQL -Bibliothek für Haskell) - Das könnte es wert sein, es zu versuchen?

Datenbanken und funktionale Programmierung können verschmolzen werden.

zum Beispiel:

Clojure ist eine funktionale Programmiersprache, die auf der relationalen Datenbanktheorie basiert.

               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

Hinweis: In der neuesten Spec2 ähnelt die Spezifikation eher RMDB. sehen: Spec-Alpha2 Wiki: Schema-und Auswahl

Ich befürworte: Erstellung eines relationalen Datenmodells auf Hash-Map, um eine Kombination aus NoSQL- und RMDB-Vorteilen zu erzielen. Dies ist tatsächlich eine umgekehrte Implementierung von Posgtresql.

Enten -Typing: Wenn es wie eine Ente und Quacksalber wie eine Ente aussieht, muss es eine Ente sein.

Wenn das Datenmodell von Clojure wie ein RMDB, die Einrichtungen von Clojure wie eine RMDB- und Clojure -Datenmanipulation wie ein RMDB, muss Clojure ein RMDB sein.

Clojure ist eine funktionale Programmiersprache, die auf der relationalen Datenbanktheorie basiert

Alles ist RMDB

Implementieren Sie das relationale Datenmodell und die Programmierung basierend auf Hash-MAP (NOSQL)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top