8

「Hibernate は常にデータベースへの呼び出しに PreparedStatement を使用します」ここで引用. その場合、hibernate はコンパイルされたクエリをどこにキャッシュし、DB ドライバーはそれらをキャッシュしますか。

c3p0について読みました。hibernate がデフォルトで PreparedStatement をキャッシュする場合、c3p0 での hibernate.c3p0.max_statements の使用は何ですか。ハイバネートがデフォルトでそれを行わない場合、準備されたステートメントをキャッシュするために接続プールが必須です。

誰かがこれらを明確にしてください。

4

1 に答える 1

13

準備済みステートメントのキャッシュは、特定の JDBC 接続の範囲内でのみ意味があります。そのため、ORM レイヤーで一種の接続プーリングが利用できる場合にのみ、プリペアド ステートメントをキャッシュすることから何かを得ることができます。そうしないと、Hibernate セッションを作成するたびに新しい「物理的な」JDBC 接続が取得されます (通常はあまり効率的ではありません)。接続プーリングを使用しない場合、プリペアド ステートメントのキャッシュは、単一の JDBC 接続/Hibernate セッションの範囲内でのみ有効です。これは、接続プールがないと、「物理」接続が実際に閉じられ、再利用されないために発生します。代わりに、必要なときはいつでも、データベース ドライバーを使用して常に新しい接続が作成されます。

考慮する必要があるもう 1 つのことは、1 つの JDBC 接続で開いている準備済みステートメントの数が制限されていることです (制限はベンダーに依存し、私の知る限り、ドライバーの実装によって異なります)。そのため、プールされた接続のシナリオでは、プーリングの実装は、プールの「物理的な」基盤となる JDBC 接続のそれぞれで、いくつのオープンな準備済みステートメントを維持できるかを知る必要があります。おそらく、「使用頻度の低い準備済みステートメントを最初に閉じる」ポリシーが実装されている可能性がありますが、これは私の純粋な憶測です。

これが意味をなすことを願っています。「物理的な」JDBC 接続について言及するときは常に、データベースへの実際の新しい TCP/IP 接続を意味します。接続プールによって取得された接続は、通常、「物理的な」接続をデコレート/ラップします。

質問に直接答える編集:

Hibernate はおそらく PreparedStatements を使用してキャッシュします (これは非常に基本的な JDBC 最適化です)。問題は、このキャッシングが「物理的」またはプール提供の JDBC 接続によって作成されたステートメントで発生するかどうかです。プールのキャッシュがない場合、PreparedStatements は、特定の Hibernate セッションのスコープで特定の PreparedStatement を 2 回使用するアプリケーション実行の一部のみを最適化します。プールを使用すると、基礎となる同じ「物理」接続をたまたま使用する多くの Hibernate Session インスタンスで同じ PreparedStatement が (効果的に) 使用されます。

hibernate 構成のプロパティ hibernate.c3p0.max_statements は、C3PO プール インスタンスを構成する可能性が最も高く (これは自動的に作成されると確信しています)、この構成は、開いている準備済みステートメントの数が制限されているという事実と関係があります。 「物理的な」JDBC 接続で。

于 2013-07-20T19:29:40.780 に答える