ORMはツリーのようなDB構造にとって悪いツールですか?


8

この質問は意見に基づくものとして締めくくられるかもしれませんが、今必要なのは議論によって裏付けられたいくつかの意見です。

PostgresとEcto(Elixir)を永続化レイヤーとして使用してアプリケーションを構築しています。それ自体を参照するエンティティがあるため、それを使用してツリーのような構造を構築できます。Ectoでこれをやろうとすればするほど、いらいらします。

ORMは、多くの関連付けを持つ複雑なDB構造を作成するための単なる悪いツールですか?ORMがリレーショナルデータに適用しようとするオブジェクト指向の方法は、ここでは悪いアプローチのようです。オブジェクトは分離されています。それらが他のオブジェクトと相互作用する場合、それらは(想定されている)メッセージを送信します。彼らの内面の詳細は隠されたままである必要があります。リレーショナルデータは、開いた透明なグラフを形成します。これら二つの世界は私と完全に両立しないようです。

しかし、ORMは非常に一般的で人気があります。Webアプリケーションの大部分はORMでうまく機能する分離されたエンティティで動作しますか、それはなぜですか?ORMフレームワークを使用して平均的に複雑なERDモデルを実装する場合は、簡潔なコードまたはパフォーマンスを犠牲にする必要があるように思われます。


1
各データベースシステムは、ツリーまたは「階層」データ構造をサポートするために、わずかに異なる実装を持つ場合があります。たとえば、OracleにはSTART WITHとCONNECT BYがあり、SQL Serverには共通テーブル式(CTE)があります。したがって、ORMを選択する前に、ORMがこれらのタイプのデータ構造を適切にサポートしているかどうかを判断する必要があります。非常に優れたサポートを提供するものもあれば、これらのシナリオをカバーしないものもあります。この質問は言い換える必要があります:Ectoはツリー構造をサポートしていますか?
Jon Raynor 2017年

postgresについて具体的に言及したので、それはこのタイプの事柄に対する再帰クエリをサポートします(私自身は使用していません)
Izkata

1
もちろんORMは悪いツールです。データベースに対するクエリを表現的に表現するための言語、SQLはすでに存在します。
マイルズルート2017年

@Miles Routほとんどの場合、ORMの代わりにプレーンSQLを使用すると、何度も繰り返します。
ジミーT.

@JimmyT。それは誤りです。
Miles Rout 2017年

回答:


9

結局のところ、ORMは、SQLを生成してデータをオブジェクトにマップする単なる抽象概念です。いくつかの「ボイラープレート」コードを保存(tm)します。

したがって、ORM全体として、定義上必ずしも不利な点はありません。問題は、ORMを全体として使用しないことです。特定のORMを選択して使用する必要があります。

個々のORMは、特定のことをうまく実行できない場合があります。ストアドプロシージャ、動的SQL、計算フィールド、複雑な結合などが問題になる可能性があります。

より微妙な問題は、ORMがこれらすべてのシナリオを一般的な方法で処理しようとすると、大きくなり、使用が複雑になることです。

大規模または複雑なアプリケーションがある場合、ある時点で、選択したORMで問題が発生する可能性があります。そのため、事前にこれを計画し、ORMをリポジトリの背後に隠すようにすることは理にかなっています。そうすれば、別の方法で自由に交換したり、必要に応じて手動でコード化されたSQLに戻ったりできます。


1
多くのORM(少なくとも私が使用したものすべて)では、生のSQLを記述して実行できることに注意してください。したがって、ORMがいくつかの制約を十分に満たさない場合は、常にネイティブSQLでORMを実行することに頼ることができ、同時にその「定型」操作をSELECT * FROM some_table WHERE x = whatever非常に一般的に減らすことができます。階層構造は一部のORMでうまく処理され、ひどく他のORMでも処理されるため、この種の考慮事項は、ORMを完全に廃止することを決定する前に調査する必要があります。
Chris Cirefice 2017年

通常はこれを行うことができますが、常に希望どおりに機能するとは限りません。最近、nHibernateとnullableフィールドマッピングでこの問題が発生しました
Ewan

私はnHibernateを使用したことがありませんが、RailsのActiveRecord、OrmLite(Java)、ActiveJdbc(Java)などを使用しました。これらの各ハンドルは、生のSQLを異なる方法で実行します。たとえば、ActiveRecordはそれを非常に簡単にし、OrmLiteはそれを非常に困難にしました。ActiveRecordは何年もの間開発されてきたので、確かにそれは何かと関係があります。これらすべての小さなニュアンスは実現可能性テストの一部ですが、後であなたに噛みつくために戻ってくる小さなものを
見落とす

ええ、だから私はそれにラッパーを付けます。あなたはまだormを使用できますが、何らかの方法でダウンさせることができる場合はロックされません
Ewan

Saving(tm)-私はこれに少し笑いました。
corsiKa 2017年

7

ORMは、多くの関連付けを持つ複雑なDB構造を作成するための単なる悪いツールですか?

いいえ。例として、Ruby on Railsは関連付けを処理するActiveRecordを使用します。ここの例では、https : //stackoverflow.com/questions/5109893/rails-how-do-self-referential-has-many-models-work、ツリーのような構造は2行のコードで実現されています。

そのため、独自のSQLクエリをロールするよりも簡単だと主張します。

Webアプリケーションの大部分はORMでうまく機能する分離されたエンティティで動作しますか、それはなぜですか?

おそらくそうではありませんが、それは当て推量です。ORMは、繁栄しているエコシステムに存在し、使用されていることを示唆しています。私は、20を超える関連モデルを持つシステムにORMを使用してきましたが、問題はありませんでした。メッセージパッシングのみでオブジェクトを分離することを強制したことはありません。

要約として、「複雑な」ERDモデルを作成している場合、それらを簡単にするツールはありません。それらを機能させるツールのみ。


はい。CustomerId(PK)とParentCustomerId(nullable FKが顧客テーブルを指す)を持つプロジェクトにEntity Frameworkを使用して、nレベルの顧客階層ツリーを作成しました。ここでは問題はありませんでした(ただし、多くのnullチェック/ .Any()LINQステートメント)
USER_8675309

Hibernate(Java)は、問題なくツリーを処理できるORMのもう1つの良い例であり、追加の労力はほとんど必要ありません。クエリの複雑さはクライアントから隠されています。親と子は遅延ロードできます。親オブジェクトIDは、データベースのもう1つの列です。子ノードの順序付きリストは、リストインデックスを保持する列を追加することで透過的にサポートすることもできます。(ここでは、順序付けされていないコレクションと順序付けされたコレクションの考慮事項は、ツリーに固有のものではありません。)
Jason C

これは誤解を招く答えだと感じざるを得ません。1つのORMがこのケースを処理するため、一般的なORMがこれを処理できるという意味ではありません。アクティブレコードは自己参照の周りのいくつかのバージョンでは落とし穴やバグ持っていることを実際に簡単にGoogleショーgithub.com/rails-api/active_model_serializers/issues/211coderwall.com/p/4d2utg/...
ユアン・

@Ewan-私は自分の答えを言い換えることは自由ですが、一般的なORMが悪い場合は、質問に適切に答えると思います。すべてのORMがこのケースを処理できるかどうか、またはそれらが最良のソリューションであるかどうかを尋ねるのは別の質問です。あまり適さないORMツールの存在、またはバージョンのバグは、一般化を変更しません。SQLにもバグがあることも知っています。
cmonkey 2017年

5

ここで少なくとも1つの他の回答で述べられているように、すべてのORMは同じではありません。一部のORMは、データベースの構造化方法について非常に重要な想定を行っています。ツールは、このモデルの外への移動をある程度サポートする必要がありますが、そのモデルの外に移動するほど、ORMの価値は低くなります。より支配的なORMツールを使用している場合、暗黙の仮定に基づいてデータベースを設計すると、はるかに優れたエクスペリエンスが得られます。

ORMがなぜ多くの開発者やアーキテクトに不可欠であると見なされているのか、私は本当に理解していません。これは、私が使用するグリーンフィールドデータベースがほとんどないためであり、ORMマッピングを実行するために必要な時間と労力は、SQLを作成するよりもはるかに多くの作業でした。マッピングが単純だった(SQLもそうだった)か、それとも複雑だったので、SQL(または類似の何か)が必要でした。私の経験では、ORMに含まれるトランザクションの「サポート」は、ヘルプよりもバグや問題の発生源でした。

マイレージはさまざまかもしれませんが、データベースの永続化をデータのシリアル化の特別なケースとして考える方がよいと私は信じるようになりました。オブジェクトをネットワーク経由で「送信」できると信じても意味がないと思うのと同じように、データベースにオブジェクトを書き込むことを考えるのはあまり意味がありません。異なるニーズに対して同じデータの複数のオブジェクト表現を持つことは完全に有効だとさえ思います。オブジェクトをテーブルにマッピングしたり、その逆を行ったりすることは、問題の解決策とは対照的に、それ自体の終わりになりました。これらのツールを使用するほとんどの人が、それを実行したい明確な理由があるとは思いません。デフォルトになりました。


1
トートは同意します。一度SQLを入力してマッピングすることを辞任すると、長期的に見るとめったに長い時間がかからず、完全に制御できます
Ewan

@Ewan公平に言うと、ロジックとDBの間の適切な抽象化を構築する方法を知るには、少し経験が必要だと思います。ORMは、開発者がすぐに機能するものに到達するのに役立ちます。これはオブジェクトをテーブルに変換できるという考え方であり、逆もまた同様で、問題があると私は思います。これは、データモデルとオブジェクトモデルのサブセットに当てはまりますが、一般的には当てはまりません。
JimmyJames 2017年

1
@JimmyJames必要なのは、テーブルごとのCRUD操作で非常に単純な場合です。それ以上に、非マイクロORMは呪いです。(そして私は個人的に、micro-ORMが戻ってくる列の異なるセットごとにオブジェクトを作成するのは面倒ですが、静的に型付けされた言語での面倒なことは少ないかもしれません。)
jpmc26

1
@ jpmc26静的な泥沼対動的泥沼を回避したいのですが、私が話していることを強調していると思います。たとえば、データをプルし、最小限の変換を行い、JSONとして返すだけであれば、実際にオブジェクトにマップする必要はありません。オブジェクトには実際の機能はありません。データが一時的に保存されるマップとして機能します。しかし、そのような問題を解決するためにORMが使用されるのを見てきました。多くの場合、答えはそれらのオブジェクトのクラスを生成することですが、それはそれらがどれほど不必要であるかを強調するだけだと思います。
JimmyJames 2017年

どういうわけか、私が最初に言うつもりでしたことを省きました:あなたが開発している真新しいデータベースでは状況は良くありません。それはあなたが書く必要があるクエリの種類にのみ依存しています。テーブルごとの非常に単純なCRUDの場合、少し時間を節約できます。ただし、さまざまなテーブルのデータを組み合わせて一致させるクエリや、複雑なクエリ(複雑なグループ化、CTE、サブクエリ)がある場合、マイクロ以外のものは自動的に問題よりもはるかに問題が多くなります。最初は非常に単純なCRUDで済むとしても、成功しても複雑さが増すことはないでしょう。
jpmc26 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.