Ich frage mich, ob ich in einem Spring + Hibernate-Projekt von Java auf Scala umsteigen kann, um einige Scala-Funktionen wie Pattern Matching, Option und eine für mich allgemein sauberere Syntax zu nutzen. Ich habe im Scala-Ökosystem standardmäßig nach dem ORM gesucht und denke dabei an "Aktivieren" (aber meistens versuche ich herauszufinden, ob Hibernate mit Scala verwendet werden kann). Auf der Suche habe ich dies in der Play-Dokumentation zu JPA + Scala gelesen .
Der wichtigste Punkt ist jedoch: Brauchen Sie wirklich einen Relationnal to Objects-Mapper, wenn Sie die Macht einer funktionalen Sprache haben? Wahrscheinlich nicht. JPA ist eine bequeme Methode, um die mangelnde Leistungsfähigkeit von Java bei der Datentransformation zu verdeutlichen, aber es fühlt sich wirklich falsch an, wenn Sie es von Scala aus verwenden.
Ich verstehe nicht genau, wie man mit funktionaler Programmierung eine vollständige Anwendung erstellt (deshalb beabsichtige ich, Scala zu verwenden, um dies schrittweise zu verstehen, da es OO + Functional kombiniert), sodass ich es nicht herausfinden kann Warum brauche ich kein ORM mit einer funktionalen Sprache und was wäre der funktionale Ansatz, um die Persistenz des Domänenmodells in Angriff zu nehmen?
Ein DDD-Ansatz für die Geschäftslogik macht bei Scala immer noch Sinn, nicht wahr?
quelle
Antworten:
Nun, eine Sache, die wichtig ist, wenn wir eine Diskussion wie diese haben, ist die klare Unterscheidung zwischen objektrelationalen Mappern ("ORM") und Datenbankabstraktionsebenen . Ein ORM ist eine Art Datenbankabstraktionsschicht, aber nicht alle Datenbankabstraktionsschichten sind ORMs. Ein gutes Werkzeug, um dies zu verstehen, ist die beliebte SQLAlchemy- Bibliothek von Python , die sich selbst als "SQL-Toolkit und objektrelationaler Mapper" (meine Fettschrift) mit der Idee ausgibt, dass dies verschiedene Dinge sind. Wie sie es auf ihrer Hauptmerkmalseite formulieren :
Die Titelseite beschreibt den ORM folgendermaßen:
Die Schlüsselidee eines ORM besteht darin, die berühmte Fehlanpassung der objektrelationalen Impedanz zu überbrücken . Dies bedeutet, dass Beziehungen zwischen benutzerdefinierten Klassen zu Tabellen in einem Datenbankschema definiert und automatische Vorgänge zum Speichern und Laden für die Klassen Ihrer Anwendung bereitgestellt werden.
Im Gegensatz dazu tendieren Nicht-ORM-Datenbankabstraktionsebenen eher zum relationalen Datenmodell und zu SQL und überhaupt nicht zur Objektorientierung. Anstatt also die „Zuordnungen“ zwischen Tabellen und Klassen und Ausblenden des Datenbankschemas von dem Programmierer, neigen sie zu entlarven , die Datenbank für den Programmierer aber mit besserer APIs und Abstraktionen. Mit SQL Query Buildern können Sie beispielsweise komplexe SQL-Abfragen programmgesteuert ohne Manipulation von Zeichenfolgen wie folgt generieren ( ein Beispiel aus der jOOQ-Bibliothek für Java ):
Nun scheint das Play-Framework nicht zu 100% mit dem übereinzustimmen , was ich gerade beschrieben habe , aber ihr Argument scheint in diesem allgemeinen Raum zu liegen: Arbeiten Sie direkt mit dem relationalen Modell, anstatt es in Klassen und umgekehrt zu übersetzen.
Die jOOQ-Bibliothek ist als Kontrapunkt zu ORMs lohnenswert. Sie haben auch einige relevante Blog-Einträge, die es wert sind, gelesen zu werden:
quelle
Es ist schwer zu erklären, bis Sie eine Menge funktionale Programmierung gemacht haben. Bei der objektorientierten Programmierung bleiben Ihre Daten sozusagen in einem Objekt stecken und bleiben dort. Dieses Objekt wird ein wenig herumgereicht und einiges verändert, aber normalerweise arbeiten Sie während der gesamten Lebensdauer dieser Daten mit derselben "Identität".
ORMs basieren im Allgemeinen auf diesem Paradigma. Sie rufen einige Daten aus der Datenbank ab, fügen sie in ein Objekt ein, ändern sie möglicherweise ein paar Mal, und wenn Sie fertig sind, haben Sie immer noch dasselbe Objekt, das Sie in die Datenbank zurückschreiben können.
Die funktionale Programmierung funktioniert anders. Ihre Daten behalten während ihrer gesamten Lebensdauer keine einzige Identität. Es wird aufgeteilt, kopiert, geteilt und transformiert. Es fließt durch eine Reihe von Funktionen und wird schließlich wieder in die Ausgabeform zusammengesetzt, die Sie benötigen. Damit sich eine Datenbank-API in einer funktionalen Sprache natürlich anfühlt, muss dies berücksichtigt werden, und JPA nicht.
quelle
In scala ist es immer noch nützlich, Datenbanktabellen Objekten zuzuordnen, und es gibt verschiedene Möglichkeiten, dies zu tun.
Ein beliebtes Framework in der Welt von Scala ist Slick . Es ist kein ORM, weil es weniger leistet (dh es ruft keine Beziehungen ab, ohne explizit dazu aufgefordert zu werden, Verknüpfungen auszuführen).
Sie ordnen Objekte weiterhin Datenbankzeilen zu, aber Ihre Objekte sind unveränderlich (daher kein State-Flush), und Sie führen Abfragen explizit mit einer monadischen DSL aus. Das Ergebnis ist, dass Sie viele der "guten" Teile eines ORM erhalten, ohne die Probleme in Bezug auf die Wandlungsfähigkeit und unvorhersehbare N + 1-Probleme.
Man sollte beachten, dass die Verwendung von viel dünneren Bibliotheken, wie Anorm oder JDBC, mit funktionalen Techniken, die den Code schön halten, große Erfolge erzielt hat .
Eine fantastische Bibliothek, die zusätzlich zu JDBC funktionale Techniken anwendet, ist auch doobie .
Sie haben also eine Menge Auswahlmöglichkeiten für den Datenbankzugriff, aber Hibernate (scheinbar der De-facto-ORM) ist nicht der beste, da er auf Veränderlichkeit ausgerichtet ist.
quelle
Sie benötigen kein ORM, auch nicht in objektorientierten Sprachen.
Erstens, wer hat gesagt, dass Ihre Daten physisch aus Ihrem dauerhaften Speicher in Ihr Objekt kopiert werden sollen? Alan Kay , ein Mann hinter Smalltalk, wollte, dass Objekte Daten loswerden . Er schlug vor, dass ein Objekt nur einen Verweis auf einen Bereich haben kann, in dem seine Daten gespeichert sind.
Zweitens - wie kann man das am besten erreichen? Ich empfehle , Ihre Objekte anhand ihrer Verantwortlichkeiten zu identifizieren und nicht an die Daten zu denken, die sie besitzen. Wenn Sie von CRC-Karten gehört haben, wird sie genau dafür verwendet.
Und für den Fall, dass Sie jemals wieder zu OO-field zurückkehren, finden Sie hier eine Möglichkeit, dies umzusetzen .
quelle