web-dev-qa-db-ja.com

Scalaのような関数型言語でORMが必要ないのはなぜですか?

Spring + HibernateプロジェクトでJavaからScalaに切り替えて、パターンマッチング、オプションなどの一部のScala機能を利用できるかどうか疑問に思っています。一般的には、構文がよりすっきりしているように見えます。私はScalaエコシステムでデフォルトでORMを探していましたが、アクティベートのように思われることがわかりました(ただし、ほとんどの場合、HibernateがScalaで使用できるかどうかを調べようとしています)。これを検索するには、JPA + Scalaについて Playドキュメント でこれを読みました。

しかし、最も重要な点は次のとおりです。関数型言語の機能がある場合、リレーショナルからオブジェクトへのマッパーが本当に必要ですか?おそらく必要ありません。 JPAは、データ変換におけるJavaの力の欠如を抽象化する便利な方法ですが、ScalaからJPAを使い始めると、それは本当に間違っていると感じます。

関数型プログラミングを使用して完全なアプリケーションを作成する方法を深く理解していません(これがScalaを使用してOOを組み合わせているため、これを段階的に理解できるようにするつもりです_ +関数型)、それで、関数型言語を使用したORMが必要ない理由と、ドメインモデルの永続性に取り組むための関数型アプローチが何であるかを理解できません。

ビジネスロジックのDDDアプローチは、Scalaでも理にかなっていますね。

30
gabrielgiussi

まあ、このような議論があるときは常にオブジェクトリレーショナルマッパー( "ORM")とデータベース抽象化レイヤー。 ORMは一種のデータベース抽象化レイヤーですが、すべてのデータベース抽象化レイヤーがORMであるとは限りません。これを把握するために検討する1つの優れたツールは、Pythonの人気のある SQLAlchemy ライブラリです。このライブラリは、「SQLツールキットandObject Relational」として機能しますマッパー」(私の太字)、これらは異なるものであるという考え。 主な機能のページ

ORMは不要

SQLAlchemyは、Core[〜#〜] orm [〜#〜と呼ばれる2つの異なるコンポーネントで構成されています]。 Coreは、それ自体が完全な機能を備えたSQL抽象化ツールキットであり、さまざまなDBAPI実装と動作、および生成Python式。DDLステートメントを発行するだけでなく、既存のスキーマをイントロスペクトできるスキーマ表現システム、およびPythonタイプのデータベースタイプへのマッピングを可能にするタイプシステム、システムを丸めるオブジェクトリレーショナルマッパーは、Coreをベースにしたオプションパッケージです。

フロントページはORMを次のように説明しています:

SQLAlchemyは、オブジェクトリレーショナルマッパー(ORM)で最も有名です。これは、データマッパーパターンを提供するオプションコンポーネントであり、クラスをオープンエンドで複数の方法でデータベースにマップできます。オブジェクトモデルとデータベーススキーマを最初からきれいに分離された方法。

ORMの重要なアイデアは、有名な object-relationalインピーダンスミスマッチ を試してブリッジすることです。これは、ユーザー定義クラスとデータベーススキーマのテーブルとの関係を定義し、アプリケーションのクラスに自動「保存」および「ロード」操作を提供することを意味します。

対照的に、非ORMデータベースの抽象化レイヤーは、リレーショナルデータモデルとSQLにコミットする傾向があり、オブジェクト指向にはまったく関与しません。したがって、テーブルとクラス間の「マッピング」を特徴とし、データベーススキーマをプログラマーから隠す代わりに、データベースをプログラマーに公開する傾向がありますが、APIと抽象化が優れています。たとえば、SQLクエリビルダーを使用すると、次のように、文字列を操作せずにプログラムで複雑なSQLクエリを生成できます( JavaのjOOQライブラリの例 )。

// Typesafely execute the SQL statement directly with jOOQ
Result<Record3<String, String, String>> result =
    create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
          .from(BOOK)
          .join(AUTHOR)
          .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID))
          .where(BOOK.PUBLISHED_IN.equal(1948))
          .fetch();

さて、 Playフレームワークは、今説明したものと100%一致していないようです ですが、彼らの議論はこの一般的な空間にあるようです:リレーショナルモデルをクラスとそれらから戻る。

jOOQライブラリ は、ORMの対置点として検討する価値があります。また、一読に値するいくつかの関連ブログエントリもあります。

30
sacundim

関数型プログラミングをたくさん行うまでは、説明するのが難しいです。オブジェクト指向プログラミングでは、データは1つのオブジェクトに詰まり、そこにとどまります。そのオブジェクトは少しの間渡され、かなり変更されますが、通常は基本的にそのデータの存続期間にわたって同じ「アイデンティティ」で作業しています。

ORMは通常、そのパラダイムを中心に設計されています。データベースから一部のデータを取得し、それをオブジェクトに変換し、場合によっては大量に変更します。完了しても、同じオブジェクトをデータベースに書き戻すことができます。

関数型プログラミングの動作は異なります。データはその存続期間を通じて単一のIDを維持しません。分割、コピー、共有、変換されます。これは一連の関数を流れ、最終的には必要な出力形式に再構成されます。すべてのデータベースAPIが関数型言語で自然に感じるには、それを考慮に入れる必要がありますが、JPAは考慮しません。

20
Karl Bielefeldt

scalaでは、データベーステーブルをオブジェクトにマップすることは依然として有用であり、それを行うにはいくつかの方法があります。

Scalaの世界で人気のあるフレームワークは slick です。それはORMではありません。それは、それよりも少ない(つまり、指示されずに関係をフェッチしない)ためです明示的に結合します)。

したがって、オブジェクトをデータベースの行にマップしますが、オブジェクトは不変であり(状態のフラッシュは行われません)、モナディックDSLを使用してクエリを明示的に実行します。その結果、ORMの「良い」部分の多くが、可変性に関する問題や予測できないN + 1の問題なしに得られます。

anorm または単純なJDBCのようなより薄いライブラリを使用して、コードを美しく保つために機能的なテクニックを使用して、人々は大きな成功を収めていることに注意してください。

JDBCの上に機能的な手法を適用する1つの素晴らしいライブラリも doobie です。

したがって、データベースアクセスには多くの選択肢がありますが、Hibernate(事実上のORMのようです)は、可変性に偏っているので、最良の選択肢の1つではありません。

10
triggerNZ

オブジェクト指向言語であってもORMは必要ありません。

最初に、データを永続ストレージからオブジェクトに物理的にコピーする必要があると誰が言ったのですか? Alan Kay 、Smalltalkの背後にいる男が欲しかった データを取り除くオブジェクト 。彼は、オブジェクトはそのデータが格納されている一部の領域への参照しか持つことができないと提案しました。

次に、それを達成するための最良の方法は何ですか?私は オブジェクトをその責任で識別する をお勧めします。オブジェクトが所有するデータについては考えないでください。 CRCカードのアプローチについて聞いたことがあれば、それはまさにそのために使用されます。

そして最後に、OOフィールドに戻る場合に備えて、ここに それを実装する方法 を示します。

0
Zapadlo