Javaプログラミング-SQLステートメントの保存場所 [閉まっている]


106

JDBC準拠のアプリケーションは、SQLステートメントをどこに保存する必要がありますか。その理由は何ですか。

これまでのところ、これらのオプションを特定することができました。

  • ビジネスオブジェクトにハードコーディング
  • SQLJ句に埋め込まれる
  • データアクセスオブジェクトなどの個別のクラスにカプセル化する
  • メタデータ駆動型(オブジェクトスキーマをデータスキーマから分離-メタデータでのそれらの間のマッピングを記述)
  • 外部ファイル(プロパティやリソースファイルなど)
  • ストアドプロシージャ

それぞれの「長所」と「短所」は何ですか?

SQLコードは「コード」または「メタデータ」と見なす必要がありますか?

ストアドプロシージャは、パフォーマンスの最適化のみに使用すべきですか、それともデータベース構造の正当な抽象化ですか?

決定はパフォーマンスが重要な要素ですか?ベンダーロックインについてどうですか?

何がより良い–疎結合または密結合とその理由?

編集:回答ありがとうございます–要約は次のとおりです:

メタデータ駆動型、つまりオブジェクトリレーショナルマッピング(ORM)

長所:

  • 非常に抽象的-モデルを変更せずにDBサーバーを切り替えることができます
  • 広範囲-実際には標準
  • 必要なSQLの量を削減
  • SQLをリソースファイルに格納できます
  • パフォーマンスは(通常)許容範囲です
  • メタデータ主導のアプローチ
  • (データベース)ベンダー非依存

短所:

  • SQLと真の開発者の意図を隠す
  • SQLはDBAによるレビュー/変更が困難
  • SQLはまだ奇妙なケースで必要になるかもしれません
  • HQLなどの独自のクエリ言語を強制的に使用できます
  • 最適化に向いていない(抽象化)
  • 参照整合性に欠ける
  • SQLの知識不足またはDBでのコーディングの注意不足の代替
  • ネイティブデータベースのパフォーマンスに決して一致しない(たとえ近づいても)
  • モデルコードはデータベースモデルと非常に緊密に結合されています

DAOレイヤーにハードコード/カプセル化

長所:

  • SQLはデータにアクセスするオブジェクトに保持されます(カプセル化)
  • SQLは書きやすい(開発速度)
  • SQLは、変更が必要なときに簡単に追跡できます
  • シンプルなソリューション(乱雑なアーキテクチャなし)

短所:

  • SQLはDBAがレビュー/変更することはできません
  • SQLはDB固有になる可能性が高い
  • SQLは保守が困難になる可能性があります

ストアドプロシージャ

長所:

  • データベースに保持されているSQL(データに近い)
  • SQLは、DBMSによって解析、コンパイル、および最適化されます。
  • SQLはDBAが簡単に確認/変更できます
  • ネットワークトラフィックを削減
  • セキュリティの向上

短所:

  • SQLはデータベースに関連付けられています(ベンダーロックイン)
  • SQLコードの保守が難しい

外部ファイル(プロパティやリソースファイルなど)

長所

  • SQLは、アプリケーションを再構築する必要なく変更できます
  • SQLロジックをアプリケーションビジネスロジックから分離
  • すべてのSQLステートメントの中央リポジトリ–保守が容易
  • 理解しやすい

短所:

  • SQLコードが保守不能になる可能性がある
  • SQLコードで(構文)エラーをチェックするのが難しい

SQLJ句に埋め込まれる

長所:

  • 構文チェックの改善

短所:

  • Javaに近すぎる
  • JDBCよりもパフォーマンスが低い
  • 動的クエリの欠如
  • あまり人気がない

良い質問ですが、一度に答えるには多すぎます。imho:p
NickDKの

+1良い質問です!@ocdecioごとに「ORM」を追加する必要があります。また、「Javaコードのどこにでも散りばめられている」(これは私が見たものであり、最悪の場合でなければならない)も追加します。
ジムフェラン2009年

2
ストアドプロシージャの下で、「SQLコードを維持するのは難しい」とは強く反対します。私のXPでは、SQLはデータベースに入ると保守が簡単でした。部分的には、外部ファイルで使用される理由(すべてのSQLステートメントの中央リポジトリー–保守が容易)に加えて、パラメーターの管理が容易になります。
マイケルロイドリーmlk

1
私の意見では、1つのオプション、ビューの使用法を見逃しています。ビューで複雑なSQLを表現し、それらのビューで単純な選択を表現することができます(DAO、SQLJ、ORMなどの任意のタイプの抽象化を使用)。ストアドプロシージャと同じような長所がありますが、短所はないと思います...
Lukas Eder

回答:


31

通常、アプリケーションのサイズや再利用性が大きくなるほど、SQLステートメントの外部化/抽象化が必要になります。

ハードコード(静的最終定数として)が最初のステップです。次のステップは、ファイル(properties / xmlファイル)に格納されます。メタデータ駆動型(Hibernate / JPAなどのORMによって行われる)が最後のステップです。

ハードコード化には、コードがDB固有になる可能性が高く、変更ごとに再書き込み/再構築/再配布する必要があるという欠点があります。利点は、1か所にあることです。

ファイルに格納すると、アプリケーションが大きくなると保守できなくなるという欠点があります。利点は、DAOメソッドを追加する必要がない限り、アプリを書き直したり再構築したりする必要がないことです。

メタデータ駆動型には、モデルコードがデータベースモデルと非常に密接に結合しているという欠点があります。データベースモデルを変更するたびに、コードを書き換える/再構築する/再配布する必要があります。利点は、それが非常に抽象的であり、モデルを変更する必要なしにDBサーバーから簡単に切り替えることができることです(しかし、今考えてみてください:会社がDBサーバーから切り替える頻度はどれくらいですか?おそらく3年に1回だけです)。それですか?)

ストアドプロシージャをこれに対する "良い"ソリューションとは呼びません。彼らは完全に異なる目的を持っています。ただし、コードは使用するDB /構成に依存します。


21

これが最適かどうかはわかりませんが、私の経験では、DAOレイヤーでハードコード(文字列リテラル)されています。


5
それはおそらく最適ではありませんが、私もそうです。書きやすく、追跡が容易で、厄介なアーキテクチャーはありません。
James Cronen、2009年

21
また、ハードコードされたSQLの追跡に費やされる時間はすべて、ジョブのセキュリティです。あなたがSQLがどこにあるかを知っている唯一の人であるなら、あなたは解雇することができません。
S.Lott、2009年

11
きちんと構築されたクリーンなOO Javaコードの作成に注意を払っている多くの人々は、乱雑でパフォーマンスの低いSQLを作成し、それを文字列としてランダムな場所に貼り付けることを許容する人々と同じであることにいつも驚かされます。SQLがDAOレイヤーの単なる文字列である場合は、チームにDBAがいないことをほぼ保証できます。少なくとも、優れた DBAではありません。
ダニエルプライデン2009年

3
-1。DAOを使用しても問題ありませんが、少なくともクエリをプロパティファイルに移動して、DBAが必要に応じてそれらを確認および調整できるようにします。
cethegeek 2009年

3
私の経験では、JDBCを直接実行している場合、ORMソリューションを使用できない場合は、クエリ文字列をデータアクセスオブジェクトレイヤーに配置するのがおそらく最善の方法です。注意が必要な場合は、同じページにいる全員がDAOクラスのコーディング標準を使用していることを確認してください。私はリソースバンドルとストアドプロシージャルートの両方をダウンさせており、データアクセスロジックを複数のレイヤーに分散しているため、どちらも絶対的なメンテナンスの悪夢でした。そのため、クエリに列を追加するには、さまざまな場所で変更する必要があります。
Jason Gritman、2009年

12

それはかなり大きな質問なので、誰かがあなたにあなたが望む賛成/反対の内訳をあなたに与えるとは思わない。代わりに、これは私が過去に使用したものであり、今後使用するものです。

私はDALでハードコーディングされたSQLを使用しています。これは、DBAがSQLを試してみたいと思うまでは問題ないと思いました。次に、それを掘り起こしてフォーマットし、DBAに配布する必要があります。誰がそれを笑って、すべてを置き換えるでしょう。しかし、適切な疑問符がないか、疑問符の順序が間違っているため、Javaコードに貼り付ける必要があります。

私たちはORMも使用しましたが、これは開発者にとっては素晴らしいことですが、SQLがないのでDBAはそれを嫌いでした。また、データベースを強制終了する癖のある奇妙なORM(サードパーティサプライヤーからのカスタムORM)も使用しました。私はそれ以来JPAを使用してきましたが、DBAを超えてJPAを使用して複雑なことをするのは大変なことです。

ストアドプロシージャを使用します(callステートメントがハードコーディングされています)。今、誰もが不満を言う最初のことは、あなたがデータベースに縛られているということです。あなたです。しかし、どのくらいの頻度でデータベースを変更しましたか?私はそれを試すことさえできないという事実を知っています。それに依存する他のコードの量に加えて、DBAの再トレーニングとデータの移行です。これは非常に高価な操作になります。しかし、あなたの世界で一瞬でDBを変更する必要がある場合、SPはおそらくアウトです。

今後は、コード生成ツールでストアドプロシージャを使用して、OracleパッケージからJavaクラスを作成したいと考えています。

2013年1月31日を編集:数年後、DBAはHibernateを使用し、絶対に必要な場合にのみSQL(DBに格納されたプロシージャ)に移行します。これが最良の解決策だと思います。DBがSQLについて心配する必要のない時間の99%、そしてそれを行う1%は、すでに快適な場所にあります。


1
+1は、ストアドプロシージャを記述してJavaコードを生成するというアイデアで、その逆ではありません。
Daniel Pryden、2009年

私の見解では、JavaレイヤーはDBレイヤーを模倣したりマップしたりすべきではありません。Oracleパッケージを抽象化しようとしている場合は、別のパッケージまたはより多くのラッピングプロシージャを作成すると思います。私は実際に2つを論理的に完全に分離しようとします。
JEキュー

2
@Xepoch:私は実際に同意します-多分私は私のコメントに別の言い方をしたはずです。データベースはデータモデル(エンティティリレーションシップモデル)のリフレクションである必要があり、オブジェクトモデルもデータモデルのリフレクションである必要があります(ただし、同一である必要はありません)。したがって、それらは少なくとも関連している必要があります。ストアドプロシージャからJavaコードを生成するという点で重要なのは、データベースにアクセスするためのAPIは、オブジェクトの構造から派生したデータモデルではなく、データモデルの構造から派生する必要があるということです。
ダニエル・プライデン2009年

jooq.orgの使用に興味があるかもしれません。「OracleパッケージからJavaクラスを作成するためのコード生成」とまったく同じです。それとは別に、JavaでSQLを表現する必要がある場合に備えて、C#のLINQに似たSQLのようなDSLが同梱されています。
Lukas Eder

10

ORM(Hibernateなど)を使用することで、心配するSQLステートメントがなくなるはずです。通常、パフォーマンスは許容範囲内であり、ベンダーからも独立しています。


13
-1 HQLステートメントがあり、ほとんどの問題はHQLに関して残っています。それらは、コード内(文字列リテラル)、注釈内の名前付きクエリ、xmlファイル内の名前付きクエリ、プロパティファイルに格納されますか?
flybywire 2009年

1
@flybywire-Hibernateでは、HQLに頼ることはまれです。98%のケースでは、例と基準(つまり、オブジェクトを使用)によるクエリで十分です。
SingleShot、2009年

2
@SingleShot、同意しません。IDによる選択よりも複雑な場合、HQL 行われると思います。基準と例は、ライブラリカタログの検索画面のように、ユーザーインターフェイス主導の検索を行うときに使用されます。しかし、他の人の考えを見てみましょう。
flybywire 2009年

3
@SingleShot-私は非常に同意しません。特にクエリのレポートには、多くのHQLを使用します。一部のHQL機能は、条件によってまったくサポートされていません(カスタムSQL関数、select句のコンストラクターを使用)。QBEは、解決するよりも多くの問題を引き起こす場合があります。
javashlook 2009年

4
「Hibernateを使用すると、HQLに頼ることはまれです」は、今日聞いた中で最もおかしなことです。QBEはばかげています。また、UIクエリの基準に頼らなければならない場合もありますが、明確に定義されたクエリ(レポート/サービスの相互作用など)はすべてHQLにする必要があります。
ChssPly76 2009年

10

SQLコードは「コード」または「メタデータ」と見なす必要がありますか?

コード。

ストアドプロシージャは、パフォーマンスの最適化のみに使用する必要がありますか、それともデータベース構造の正当な抽象化ですか?

ストアドプロシージャは、他のストアドプロシージャの内部を含む再利用を可能にします。つまり、データベースに1回アクセスして、サポートの指示を実行させることができます。最小限のトラフィックが理想的です。ORMまたはsproc、db&backに行くまでの時間は、回収できないものです。

ORMは抽象化されているため、最適化に適していません。IME、ORMは、参照整合性の欠如も意味します-データベースからの報告を困難にします。複雑さを軽減するために保存されていたものは、データを実用的な方法で取り出すことができるようになりました。

決定はパフォーマンスが重要な要素ですか?ベンダーロックインについてはどうですか?

いいえ、シンプルです。ベンダーロックインはデータベースでも発生します。SQLは比較的標準化されていますが、ベンダー固有の方法があります。


4
SQLコードを呼び出すための+1。あまりにも多くのORMツールがSQLを隠そうとしますが、実際、SQLは、実行しようとしていることを表現するのに最適な言語であることがよくあります。そして、ストアドプロシージャはORMよりも優れているというあなたの意見に同意しますが、ここでは一般的な意見になるとは思いません。
ダニエル・プライデン2009年

9

Javaの世界におけるベンダーロックインへの恐怖は興味深いものです。

Oracle EnterpriseのCPUあたり50000ドルを支払っていないことを望みます。その後、MySQLに少しずつ切り替えるために、最も一般的な分母のみを使用しました。優れたDBAが言うように、特にロックモデルと、それらがどのように一貫性を実現するかに関して、異なるビッグネームデータベースの間には微妙な違いがあります。

そのため、ベンダーにとらわれないSQLの原則のみに基づいてSQL呼び出しを実装する方法を決定しないでください。そうするのには、実際の(ビジネス上の)理由があります。


1
ああ、そんなことはありません!主な関心事は、サポートチームがSQLステートメントを変更できるようにし(たとえば、チューニング、DBA関連のタスク)、アプリケーションが(データベースに関連して)何をするかについての可視性を向上させることです。サポートチームはJavaのノウハウを持っていないため、コードを詳しく調べてみてください。アプリケーションは、すべてIngresデータベースを使用して、既存のアプリケーションの大規模な資産に新たに追加されます
Adrian

6

ストアドプロシージャ内のSQLは、データベースシステムによって最適化され、速度が向上するようにコンパイルされています。SQLはデータベースシステムによって認識され、データベースシステムによって解析されます。可能であれば、SQLをデータベースに保存します。ストアドプロシージャや関数、またはデータベースシステムが提供するロジックの任意の単位でそれをラップし、あなたまたは他の誰かが言及したツールのいずれかを使用して、それを簡単に呼び出します。

なぜデータベースシステムのSQLコードをデータベースの外部に格納するのですか?多くの場合、開発のスピードのためです。ORMマッピングを使用する理由 -ORMマッピングは異なるデータベースシステム間の互換性を提供すると言う人もいます。ただし、実際には、アプリケーションが構築されたときに、特にレプリケーションなどの高度な機能の使用を開始したときに、アプリケーションがデータベースプラットフォームからシフトすることはめったにありません。まれに、データベースシステムがスワップアウトされることがあり、一部の作業が保証されます。ORMの欠点の1つは、SQLの知識の欠如またはdbでのコーディングの注意の欠如の代わりになることが多いと思います。また、ORMは、たとえ近づいても、ネイティブデータベースのパフォーマンスに決して一致しません。

私はSQLコードをデータベースに保持し、使用したいAPIまたはインターフェースを介してSQLコードを簡単に呼び出す側に立っています。また、これらの呼び出しを抽象クラスまたはOOインターフェース(メソッドで表現)の背後に置くことにより、データベース呼び出しが行われるポイントを抽象化します。これにより、新しい種類のデータソースでスワップを行う場合でも、ビジネスレイヤーにシームレスになります。 。


+1素晴らしい見方。あなたはこのブログの投稿に興味があると思います:database-programmer.blogspot.com/2010/12/…
Lukas Eder

5

明確な答えがある唯一の質問は、「SQLコードまたはメタデータですか?」です。これは、最も確実コードで、などは、ソースコード管理のいくつかの種類に保管し、簡単に最新バージョンにアップデートするとバックをロールするためのシステムを持っているべきであるとき、物事がうまくいかない場合。

アプリケーションでSQLを実行する3つの方法を見てきましたが、それぞれに長所と短所があります。最善の方法はありませんが、最良の方法は、アプリケーションで適切に機能するものを1つ選び、それを使い続けることです。

  • ORM-これにより、作成する必要のあるSQLの量が削減され、多くの詳細が処理されます。カスタムSQLを実行する必要があります。これを適切に処理するORMがあることを確認してください。
  • データアクセスオブジェクト-データにアクセスするオブジェクトにSQLを保持します。これにより、データベースがカプセル化され、アプリケーションの残りの部分は、基盤となるDB構造について知る必要がなくなります。これらのオブジェクトへのインターフェースだけが必要です。
  • ストアドプロシージャ-すべてのSQLをデータベースに保持し、DBAが何が起こっているかを簡単に知ることができます。あなたがする必要があるのはあなたのコードがストアドプロシージャを呼び出すことだけです

4

私たちはたまたま、HibernateのようなORMよりも金属に近いiBatis SQLマッパーを使用しています。iBatisでは、SQLステートメントをリソースファイル(XML)に入れます。これはクラスパスにある必要があります。

@ocdecioのORMオプションを追加すると、アプローチのリストはかなり包括的になります。ORMを使用することと、SQLマッパーとリソースファイルを使用することが、2つの最良のアプローチだと思います。SQLJは避けた方がよいでしょう。SQLJはあまり取り上げられておらず、Javaとの結びつきが強すぎます。また、特定のデータベースベンダーと結びついているため、ストアドプロシージャには近づかないでください(ストアドプロシージャの標準はほとんどありません)。


4

私たちのほとんどと同様に、私はガムット全体を見てきましたが、SQLを第一級言語と考える必要があります。DBにSQLが格納され、プルダウンされてから実行されるSQLを見たことさえあります。

私が見た中で最も成功したシステムは、ストアドプロシージャ、関数、ビューを採用しています。

ストアドプロシージャは、SQLテキストをDBに戻し、展開とカスタマイズ(比較的多くの適切な設計をサポートする必要がある)による比較的即時の変更を可能にします。

すべての投影は、同じ理由でビューと単純な選択を介して行う必要があります。すべての投影ロジックはビュー内に含まれている必要があります。


ビューに言及するための+1。これは質問の要約にはまだ反映されていません
Lukas Eder

2

ファクトリレイアウトでDAOを使用することをお勧めします。したがって、必要なサンプルオブジェクトは次のようになります。

public class CoolBusinessObject
public class DAOFactory.java
public implementation CoolBusinessOjectDAO
public class CoolBusinessOjectDAOOracleImpl implements CoolBusinessOjectDAO

このスタイルはデータの相互作用を階層化するため、データベースを切り替えるかORMテクノロジに移行する場合は、コードの1つの層を変更するだけで済みます。


2

これら3つの間には、実質的な違いはありません。

  1. ビジネスオブジェクトにハードコーディング
  2. SQLJ句に埋め込まれる
  3. データアクセスオブジェクトなどの個別のクラスにカプセル化する

SQLコードを文字列形式でJavaコードに直接埋め込むことを想定しています。1と3はおそらく直接JDBC(またはApache DbUtilsなどのツール)を使用しますが、2はスタックにプリプロセッサテクノロジーを追加し、コンパイルの前に関連するJDBCコードを生成します。

したがって、基本的に、これらのソリューションにSQLの埋め込みが含まれる場合は、以下のテクノロジーのいずれかを使用することもできます。

  • JPA Criteria API、JPQLをJavaの内部ドメイン固有言語としてモデル化
  • jOOQ、SQLをJavaの内部ドメイン固有言語としてモデリング

SQLJを使用したり、実際の文字列連結を使用したりするよりもタイプセーフな方法でSQLをJavaに埋め込むのに役立つ他のツールもあります。


1

私の経験から、DAOオブジェクトにSQLステートメントをハードコーディングすることは広く使用されていますが、最も好ましい方法ではないはずです。ベストプラクティスは、sqlステートメントをプロパティファイルに格納することです。そして、プロパティファイルへのインターフェイスを介して、DAOオブジェクトのステートメントを取得します(たとえば、java.util.Properties)。SQLステートメントに「?」を挿入して、Prepared Statementアプローチを通じてパラメーターを渡すことができます。

このようなアプローチは、SQLロジックをアプリケーションビジネスロジックから分離するのに役立ちます。これにより、すべてのSQLステートメントの中央リポジトリが利用可能になり、変更が容易になり、アプリケーションロジック内でデータベースステートメントを検索する必要がなくなります。理解しやすさも向上します。


一部の人々は、これがSQLインジェクションのリスクをもたらすことに反対するかもしれません。それについてどう思いますか?
エイドリアン

2
とにかくアプリケーションの外でSQLコードを格納している場合、それをデータベースレイヤーに(ストアドプロシージャとして)格納するよりもどこかに文字列として格納することの利点は何ですか?ストアドプロシージャはデータベースのオプティマイザをより効果的に使用できるため、ほとんどの場合、準備されたステートメントよりもパフォーマンスが優れています。
ダニエル・プライデン2009年

1
こんにちはダニエル、私は意味しませんでした、あなたはsql procを書かないでください、私はただ、あなたが格納されたprocを呼び出すという意味で、私は述べました。ストアドプロシージャへのパラメータの受け渡しをより適切に制御するのにも役立ちます。
The Machine、

1

鉱山は最終的にリソースバンドルになります。私はそれが正常ではないことを知っていますが、私と「私以外の」誰にとっても維持するのが最も簡単です。それは簡単で論理的です。

私も実際に誰かが私のアプローチを使用しているかどうかを知りたいと思っています。


SQLをDBに保持しないのはなぜですか?
JEキュー

@Xepoch-どういう意味ですか?ステートメントはエンティティと同じパッケージ内のリソースバンドル(プロパティファイル)にあるため、customer.propertiesはCustomer.classに関連しています。データはDBに保存されます。
ブレット・ライアン

1

rexemはSQL ステートメントをコードとして記述しているため、それらはコードのように扱う必要があります(正当な理由がない限り)外部化せずに、そのステートメントとの間のSQLデータを処理するコードを配置します。今日のフレームワークORM / iBatisは、日々のJDBC開発を大幅に簡素化します。

この質問にある質問に対するいくつかの回答:) SQLステートメントがどのように格納されるかという問題は、アプリケーションの王様によって異なります。あなたのニーズは何ですか?高いセキュリティ、コードの記述やメンテナンスの容易さ、クロスプラットフォームまたはベンダーのロックイン?次の質問では、純粋なSQLまたはORMフレームワークが良いでしょうか。

* Hardcoded in business objects
* Encapsulate in separate classes e.g. Data Access Objects

最もシンプルなソリューション(P)、維持が困難(C)

* Embedded in SQLJ clauses

より良い構文チェック(P)、OD動的クエリの欠如(C)、JDBCよりも低いパフォーマンス(C)、それほど人気が​​ない(C)

* Metadata driven (decouple the object schema from the data schema - describe the mappings between them in metadata)

特定のケースでなければなりません(C)またはORMを意味する場合(P);)

* External files (e.g. Properties or Resource files)

管理しやすい(P)が、エラーのチェックが難しい(C)

* Stored Procedures

高いセキュリティ(P)、ベンダーロックインの問題を管理するのが難しいコード(C)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.