web-dev-qa-db-ja.com

HibernateまたはJDBC

シッククライアントがあります。Java 25テーブルのスキーマと〜15 JInternalFrames(テーブルのデータ入力フォーム)を持つs​​wingアプリケーション。ストレートJDBCまたはORM( DBMSフレームワークとのやり取りのために、この場合は春のフレームワークで休止状態になります。アプリケーションのビルドは将来行われます。

このサイズのプロジェクトでは、休止状態は過剰になりますか? 「はい」または「いいえ」の回答の説明をいただければ幸いです(正当な場合は別のアプローチも可能です)。

TIA。

68
jmq

単一の単純な答えのない良い質問です。

私は、複数年にわたって複数のプロジェクトでHibernateを使用した後、Hibernateの大ファンでした。私は、どのプロジェクトもデフォルトで休止状態にすべきだと信じていました。

今日はよくわかりません。

Hibernate(およびJPA)は、特に開発サイクルの初期のいくつかの点で優れています。 JDBCを使用するよりも、Hibernateを使用して作業する方がはるかに高速です。キャッシング、楽観的ロックなど、多くの機能を無料で利用できます。

一方、いくつかの隠れたコストがあります。 Hibernateは開始時に非常に単純です。いくつかのチュートリアルに従って、クラスに注釈を付けてください。そうすれば、永続性が得られます。しかし、それは単純ではなく、その中に適切なコードを書くことができるためには、内部の仕組みとデータベース設計の両方をよく理解する必要があります。始めたばかりの場合は、後で噛むかもしれない問題に気づかないかもしれませんので、ここに不完全なリストがあります。

パフォーマンス

実行時のパフォーマンスは十分です。productionで、休止状態がパフォーマンス低下の原因である状況はまだ見ていません。問題は、起動時のパフォーマンスと、単体テストの時間と開発パフォーマンスにどのように影響するかです。休止状態が読み込まれると、すべてのエンティティを分析し、事前キャッシュを大量に実行します。それほど大きくないアプリケーションの場合、約5〜10〜15秒かかります。したがって、1秒の単体テストには11秒かかります。楽しくない。

データベースの独立性

データベースを微調整する必要がない限り、とてもクールです。

インメモリセッション

Hibernateは、トランザクションごとに、「タッチ」するデータベース行ごとにオブジェクトをメモリに保存します。簡単なデータ入力を行うとき、それは素晴らしい最適化です。ただし、何らかの理由で大量のオブジェクトを処理する必要がある場合は、明示的に慎重にメモリ内セッションを自分でクリーンアップしない限り、パフォーマンスに深刻な影響を与える可能性があります。

カスケード

カスケードにより、オブジェクトグラフの操作を簡素化できます。たとえば、ルートオブジェクトといくつかの子があり、ルートオブジェクトを保存する場合、子を保存するようにhibernateを構成できます。問題は、オブジェクトグラフが複雑になったときに始まります。細心の注意を払い、内部で何が起こっているのかを十分に理解していない限り、これを台無しにするのは簡単です。また、これらの問題をデバッグするのは非常に困難です。

遅延読み込み

遅延読み込みとは、オブジェクトを読み込むたびに、hibernateは関連するすべてのオブジェクトを読み込むのではなく、代わりにアクセスしようとすると解決されるプレースホルダーを提供することを意味します。最適化の最適化?ただし、この動作に注意する必要がある場合を除き、暗号化エラーが発生します。例については、Google「LazyInitializationException」。そして、パフォーマンスに注意してください。オブジェクトのロード方法とオブジェクトグラフの順序によっては、「n + 1 select problem」がヒットする場合があります。 Googleで詳細を確認してください。

スキーマのアップグレード

Hibernateでは、Javaコードをリファクタリングして再起動するだけで、簡単にスキーマを変更できます。起動時に最適です。しかし、バージョン1をリリースします。スクリプト:これは、すべてのスキーマ変更をSQLで行う必要があるため、これ以上単純なリファクタリングが不要になることを意味します。

ビューとストアドプロシージャ

Hibernateは、動作するデータへの排他的書き込みアクセスを必要とします。つまり、ビュー、ストアドプロシージャ、およびトリガーを使用することはできません。これらは、それらを認識せずに休止状態でデータを変更する可能性があるためです。別のトランザクションでデータベースにデータを書き込むいくつかの外部プロセスを持つことができます。ただし、その場合、キャッシュには無効なデータが含まれます。これはもう1つ気になります。

シングルスレッドセッション

Hibernateセッションはシングルスレッドです。セッションを介してロードされたオブジェクトは、同じスレッドからのみアクセス(読み取りを含む)できます。これはサーバー側のアプリケーションには受け入れられますが、GUIベースのアプリケーションを実行している場合は不要なことが複雑になる可能性があります。

私のポイントは無料の食事はありません。

Hibernateは優れたツールですが、複雑なツールであり、適切に理解するには時間がかかります。あなたやあなたのチームメンバーがそのような知識を持っていない場合、単一のアプリケーションに対して純粋なJDBC(またはSpring JDBC)を使用する方が簡単かつ迅速です。一方で、学習することに時間を費やしたい場合(実行とデバッグによる学習を含む)は、将来的にトレードオフをよりよく理解できるようになります。

184

Hibernateは良い場合もありますが、Hibernateと他のJPA ORMは、ある程度データベース構造を決定する傾向があります。たとえば、複合主キーはHibernate/JPAで実行できますが、少し厄介です。他の例もあります。

SQLに慣れている場合は、 Ibatis をご覧になることを強くお勧めします。 Hibernateの90%以上を実行できますが、実装ははるかに簡単です。

IbatisよりもストレートJDBC(またはSpring JDBC)を選択した理由は1つだけではありません。 Hibernateはより複雑な選択肢です。

Spring and Ibatis Tutorial をご覧ください。

20
cletus

間違いなくHibernateには複雑さがあります。

しかし、Hibernateアプローチ(他の一部のアプローチも)で私が本当に気に入っているのは、Javaで取得できる概念モデルの方が優れていることです。私はOOを万能薬とは考えていませんが、デザインの理論的な純度を探していませんが、OOが実際にコードを単純化することを何度も見つけました。詳細を具体的に尋ねたので、いくつか例を示します。

  • 追加された複雑度はモデルにありませんおよびエンティティーですが、たとえばすべてのエンティティーを操作するためのフレームワークにあります。メンテナーにとって、ハードな部分はいくつかのフレームワーククラスではなく、モデルなので、Hibernateを使用するとハードな部分(モデル)を最もクリーンに保つことができます。

  • フィールド(IDや監査フィールドなど)がすべてのエンティティで使用されている場合、superclassを作成できます。したがって:

    • 書くコードは少なくなりますが、もっと重要なことは...
    • モデルに含まれる概念が少ない(固有の概念はコード内で固有です)
    • エンティティ(不明、タイプ切り替えまたはキャストなし)を備えたIDにアクセスできる、より汎用的なコードを無料で作成できます。
  • Hibernateには、必要な他のモデル特性に対処するための多くの機能もあります(現在または後で、必要な場合にのみ追加してください)。 拡張性デザインの品質と考えてください。

    • 継承(サブクラス化)を構成(複数のエンティティで必要になるいくつかの関連フィールドを含む同じメンバーを持つ複数のエンティティ)に置き換えることができます。
    • いくつかのエンティティ間に継承が存在する場合があります。ほとんど同じ構造のテーブルが2つあることがよくあります(ただし、別の親テーブルへの参照整合性が失われるため、すべてのデータを1つのテーブルに格納する必要はありません)。
  • エンティティ間の再利用(ただし、適切な継承、および構成のみ)には、通常、追加の利点がいくつかあります。例:

    • 多くの場合、類似しているが異なるエンティティのデータを読み取る方法がいくつかあります。 3つのエンティティの「タイトル」フィールドを読み取ったとしますが、一部のエンティティでは、結果がnullの場合は異なるデフォルト値に置き換えられます。シグネチャ「getActualTitle」(スーパークラスまたはインターフェース)を持ち、3つの実装でデフォルト値の処理を実装するのは簡単です。つまり、エンティティからのコードは「実際のタイトル」の概念を処理するだけであり(この機能概念を明示的にしました)、メソッドの継承が正しいコードの実行を処理します(スイッチの切り替えやコードの重複がない場合) 。
    • ...
  • 時間が経つにつれて、要件は進化します。データベース構造に問題がある箇所があります。 JDBCのみでは、データベースへの変更はコードに影響を与える必要があります(つまり、二重のコスト)。 Hibernateでは、コードではなくマッピングのみを変更することで多くの変更を吸収できます。 Hibernateでは、データベースを変更せずに(たとえばバージョン間で)コードを変更できます(常に十分ではありませんが、マッピングを変更します)。要約すると、Hibernateはデータベースとコードを独立して進化させますです。

これらすべての理由から、Hibernateを選択します:-)

12
KLE

私はどちらかが良い選択だと思いますが、個人的には休止状態を使用します。そのサイズのプロジェクトでは、休止状態が過剰だとは思わない。

Hibernateが本当に素晴らしいのは、エンティティ/テーブル間の関係を扱うことです。親と子(孫、兄弟など)を同時に変更する場合、JDBCを手作業で行うと多くのコードが必要になります。 Hibernateはこれを簡単にすることができます(多くの場合、親エンティティを1回保存するだけで十分です)。

ただし、Hibernateを処理する際には、セッションフラッシュの仕組みを理解したり、遅延読み込みを処理するなど、確かに複雑さがあります。

5
Brian Yarger

Hibernateはミドルウェアアプリケーションに最適です。データベースの上にミドルウェアを構築すると仮定します。この場合、20のアプリケーションすべての要件を満たす休止状態を持たせることができる約20のアプリケーションがミドルウェアにアクセスします。

3
Asok B

ストレートJDBCは、せいぜい最も単純なケースに適合します。

JavaおよびOOD内に留まる場合は、HibernateまたはHibernate/JPAまたはany-other-JPA-provider/JPAを選択する必要があります。

SQLに慣れている場合は、Spring for JDBCテンプレートや他のSQL指向のフレームワークを使用しても問題はありません。

対照的に、トランザクション制御に加えて、JPAで作業するときにSpringを使用することによる大きな助けはありません。

3
topchef
  1. JDBCでは、データベース接続を開く場合、tryを記述する必要があります。例外が発生した場合、catchブロックはそれを受け取り、最終的に接続を閉じるために使用します。

  2. Jdbcでは、すべての例外はチェック例外であるため、try、catch、およびthrowsでコードを記述する必要がありますが、休止状態では未チェック例外のみがあります。

  3. ここでプログラマーとして接続を閉じる必要があります。そうしないと、接続メッセージを受け取る機会が得られます…!

  4. 実際、finallyブロックで接続を閉じなかった場合、jdbcはその接続を閉じる責任を負いません。

  5. JDBCでは、さまざまな場所にSqlコマンドを記述する必要があります。プログラムが作成された後、テーブル構造が変更された場合、JDBCプログラムは機能しません。

  6. JDBCは、例外が発生した場合にデータベース関連のエラーコードを生成するために使用されていましたが、Javaこのエラーコードについてプログラマは不明です。

  7. レコードを挿入しているときに、データベースに特定のテーブルがない場合、JDBCは「View not exist」などのエラーを発生させ、例外をスローしますが、休止状態の場合、テーブルが見つからない場合データベースこれはテーブルを作成します

  8. JDBCはLAZYロードをサポートし、HibernateはEagerロードをサポートします

  9. Hibernateは継承、関連付け、コレクションをサポートします

  10. Hibernateでは、派生クラスオブジェクトを保存すると、その基本クラスオブジェクトもデータベースに格納されます。これは、hibernateが継承をサポートすることを意味します

  11. Hibernateは、1対多、1対1、多対多、多対1などの関係をサポートします

  12. Hibernateはこれによりキャッシングメカニズムをサポートします。アプリケーションとデータベース間のラウンドトリップの回数が削減されます。このキャッシング技術を使用することにより、アプリケーションのパフォーマンスが自動的に向上します。

  13. 休止状態でページネーションを取得するのは非常に簡単です。

  14. Hibernateには、レコードをデータベースに保存している間に主キーを自動的に生成する機能があります

1
Creditto

...メモリ内セッション... LazyInitializationException ...

セッションオブジェクトを使用しない Ebean ORM を見ることができます。確かにオプションであり、やり過ぎではなく、理解しやすいでしょう。

0
Rob Bygrave

何十億人ものユーザーがアプリやウェブを使用している場合、jdbcクエリでは何十億時間も実行されますが、hibernateクエリでは、jdbcに対するhibernateの最も重要で簡単な利点の任意の数のユーザーに対して1回だけ実行されます。

0
Ankesh Roy