質問

Javaサーブレットでデータベース接続を管理する最良の方法は何ですか?

現在、単に init()関数で接続を開き、次に destroy()で閉じます。

ただし、「永久に」という懸念があります。データベース接続を保持するのは悪いことです。

これはこれを処理する正しい方法ですか?そうでない場合、いくつかのより良いオプションは何ですか?

編集:もう少し明確にするために:リクエストごとに新しい接続を単に開いたり閉じたりしようとしましたが、テストでは接続が多すぎるためにパフォーマンスの問題が発生しました。

複数のリクエストで接続を共有することに価値はありますか?このアプリケーションのリクエストは、ほぼすべて「読み取り専用」です。かなり迅速に届きます(ただし、要求されたデータはかなり小さいです)。

役に立ちましたか?

解決

実際には、Commons DBCPの使用に同意しません。接続プーリングを管理するには、コンテナに実際に従う必要があります。

Javaサーブレットを使用しているので、サーブレットコンテナで実行することを意味し、私が使い慣れているすべての主要なサーブレットコンテナは接続プール管理を提供します(Java EE仕様ではそれが必要になる場合もあります)。コンテナーが(Tomcatのように)DBCPを使用する場合、それ以外の場合は、コンテナーが提供するものをすべて使用します。

他のヒント

誰もが言うように、接続プールを使用する必要があります。どうして?どうした?その他

ソリューションの問題点

これは、昔々良いアイデアだと思っていたので知っています。問題は2つあります:

  1. すべてのスレッド(サーブレットリクエストはそれぞれ1つのスレッドで処理されます)は同じ接続を共有します。したがって、要求は一度に1つずつ処理されます。 1つのブラウザに座ってF5キーに頼るだけでも、これは非常に遅くなります。試してみてください:これらは高レベルで抽象的に聞こえますが、経験的でテスト可能です。
  2. 何らかの理由で接続が切断された場合、initメソッドは再度呼び出されません(サーブレットのサービスが停止されないため)。 doGetやdoPostにtry-catchを入れてこの問題を処理しようとしないでください。そうすると、あなたは地獄にいることになります(尋ねられることなくアプリサーバーを作成するようなものです)。
  3. 考えられることとは反対に、トランザクションの開始は接続だけでなくスレッドに関連付けられるため、トランザクションに問題はありません。私は間違っているかもしれませんが、とにかくこれは悪い解決策なので、汗をかかないでください。

接続プールの理由

接続プールには多くの利点がありますが、何よりも問題は解決します

  1. 実際のデータベース接続の作成にはコストがかかります。接続プールには常にいくつかの余分な接続があり、それらのいずれかを提供します。
  2. 接続が失敗した場合、接続プールは新しい接続を開く方法を認識しています
  3. 非常に重要:すべてのスレッドが独自の接続を取得します。これは、スレッドが本来あるべき場所であるDBレベルで処理されることを意味します。 DBは非常に効率的で、同時要求を簡単に処理できます。
  4. その他のもの(JDBC接続文字列の場所の一元化など)が、これには数百万の記事、書籍などがあります

接続を取得するタイミング

サービスデリゲートで開始されたコールスタックのどこか(doPost、doGet、doDiscoなど)で接続を取得し、正しいことをして、最終ブロックでそれを返す必要があります。 C#のメインアーキテクトの男が、 catch ブロックの100倍以上の finally ブロックを使用する必要があると一度言ったことに言及する必要があります。真実の言葉は決して話されません...

どの接続プール

サーブレットを使用しているため、コンテナが提供する接続プールを使用する必要があります。接続を取得する方法を除き、JNDIコードは完全に正常です。私の知る限り、すべてのサーブレットコンテナには接続プールがあります。

上記の回答に関するコメントのいくつかは、代わりに特定の接続プールAPIを使用することを提案しています。 WARは移植可能で、「展開するだけ」でなければなりません。これは基本的に間違っていると思います。コンテナが提供する接続プールを使用する場合、アプリは、複数のマシンとJava EE仕様が提供するすべての豪華なものにまたがるコンテナにデプロイできます。はい、コンテナ固有のデプロイメント記述子を作成する必要がありますが、それはEEの方法です。

あるコメンターは、コンテナが提供する特定の接続プールはJDBCドライバーでは動作しないと述べています(Websphereについて言及しています)。それは完全に大げさでばかげているように聞こえるので、おそらく本当です。そのようなことが起こったら、あなたが「しなければならない」ことをすべて投げてください。ごみの中にあなたができることは何でもします。それは私たちが支払いを受けるものです、時々:)

Commons DBCP を使用します。接続プールを管理するApacheプロジェクトです。

doGetまたはdoPostで接続を取得してクエリを実行し、finallyブロックで接続を閉じます。 (con.close()はそれをプールに返すだけで、実際には閉じません。)

DBCPは、接続タイムアウトを管理し、それらから回復できます。データベースが一定期間停止した場合の現在の方法は、アプリケーションを再起動する必要があります。

接続をプールしていますか?そうでない場合は、おそらく接続を開いたり閉じたりするオーバーヘッドを減らす必要があります。

John

最良の方法は、現在Googleでより良いリファレンスシートを探しているのですが、プールを使用することです。

初期化時に、データベースへのX個のSQL接続オブジェクトを含むプールを作成します。これらのオブジェクトをArrayListなどのある種のリストに保存します。これらの各オブジェクトには、 'isLeased'のプライベートブール値、最後に使用された時間の長い値、および接続があります。接続が必要なときはいつでも、プールから接続を要求します。プールは、isLeased変数をチェックして、最初に利用可能な接続を提供するか、新しい接続を作成してプールに追加します。タイムスタンプを設定してください。接続が完了したら、それをプールに返すだけで、isLeasedがfalseに設定されます。

データベースが常に接続されないようにするために、プールをときどき通過して、最後に接続が使用された時刻を確認するワーカースレッドを作成できます。十分に長い場合は、その接続を閉じてプールから削除できます。

これを使用する利点は、Connectionオブジェクトがデータベースに接続するのを待つ長い待ち時間がないことです。すでに確立された接続は、好きなだけ再利用できます。そして、あなたはあなたのアプリケーションがどれくらい忙しいと思うかに基づいて接続の数を設定することができるでしょう。

データベース接続は、必要な間だけ開いておく必要があります。これは、実行している内容に応じて、おそらく doGet / doPost メソッドのスコープ内にあります。

プール。

また、未加工のJDBCを使用している場合、Connection、PreparedStatementなどの管理に役立つ何かを調べることができます。たとえば、SpringのJDBCサポートを使用すると、コードが大幅に簡素化され、Springの他の部分を使用する必要がなくなります。

こちらの例をご覧ください:

http://static.springframework.org/spring /docs/2.5.x/reference/jdbc.html

データソースに関連付けられた接続プールがトリックを行う必要があります。サーブレットリクエストメソッド( doget / dopost など)のdataSourceから接続を取得できます。

dbcp、c3p0、および他の多くの接続プールは、探していることを実行できます。接続をプールしている間に、StatementsとPreparedStatementsをプールすることができます。また、あなたが示したようにREAD HEAVY環境の場合、ehcacheのようなものを使用して結果の一部をキャッシュすることもできます。

BR、
〜A

通常、リクエストごとに接続を開く方が管理しやすいことがわかります。つまり、サーブレットのdoPost()またはdoGet()メソッドで。

init()で開くと、すべてのリクエストで利用できるようになりますが、同時リクエストがあるとどうなりますか?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top