2016-04-28 2 views
2

まず、データポイントはほとんど提供していません。
次の問題が説明されます。複数の読み取り専用トランザクションを1つのJDBC接続で多重化することは可能ですか


データポイント:
[D1] HibernateAnnotationmanaged objects世界、私はHibernateのトランザクションが開始された管理対象Beanで

@Transactional 
public void createStuff(..){ 
// get entity manager and call persist and other operatation 
} 
@Transactional 
public SomeDtoObject getStuff(..){ 
// get entity manager and call find and getter to polulate a object to return 
} 

のような一般的なパターンを見てきたものこのメソッドを呼び出すとコミットされます。

Hibernateのドキュメントは述べています(link):

マルチユーザーのクライアント/サーバアプリケーションで最も一般的なパターンは、セッションごとの要求です。

[D2]また、Postgresのドキュメント(link)上で述べたように、データベースへの接続は、接続プールのライブラリC3P0を使用してプールされるべきであることをお勧めします

Pgは通常、同じ万件のトランザクションを完了します5回、10回、または20回を一度に行うよりも、一度に500回行う方が速いです。

[D3]また
JDBCと私たちはそのトランザクション内で好きなように我々は一度取引とできるだけ多くのステートメントを実行することができ、単一の接続を考えます。
2つの異なるトランザクションメソッドを実行する2つの異なるスレッドが同じ接続を使用してはならず、もう1つのメソッドを呼び出す前に待機する必要があることをアプリケーション(C3P0)が確認できるようにします。


問題:私たちは、接続プールと一緒に注釈を使用して管理対象Beanのトランザクションパターンを使用している場合
は今休止状態とセッションごとの要求に(レッツは1つの接続でのみ言う)
も(コードは今二つの異なるスレッドがあると想像

@Transactional 
public SomeDtoObject getStuff(..){ 
// get entity manager and call find and getter to polulate a object to return 
SomeEntity se = entityManager.find(someentity, primaryKey); 
//create Dtos 
// access someEntity to all over this method to create SomeDtoObject that we have to return. 
// also may access some file on system to fetch some data is order to populate someDtoObject. 
// overall let say the method take 150 milli second to do all its work 
} 

のようなものであるとしましょう(...) T1が呼び出され、接続プールからjdbc接続を取得します。
そして、T2entityManager.findに達すると、C3P0は接続が残っていないことをチェックし、T1が約150ミリ秒かかる完了までT2を保留にします。

getStuff(...)が読み取り専用クエリを実行するとすれば、両方のスレッドが同じ接続を使用でき、スレッドがクエリを実行しないようにすることが理想的です。
上記のケースでは、その接続をアイドル状態にしておき、スレッドを待機させます。

MAIN QUESTION
私は特定の休止状態のトランザクションが読み取り専用であることを休止して、代わりに、接続プールからの新しい接続を求めての、すでに取得した接続を再利用することができ休止すると言うことができる方法はありますか?


少数のソリューションは/が示唆された:(説得力のない)

1あなたはそんなに心配している場合は、注釈を使用してトランザクションを使用していけない、HibernateのSessionを自分で使用する.....なしIそのパターンのように)
2ConnectionRelease オプションを提供することができますafter_statementに設定することができます。
最初 Hibernate C3P0接続プールプロバイダはafter_statementをサポートしていません。
第2これはオーバーヘッドになり、接続を再確立します。

+0

プールに複数の接続があっただけで問題はありません。それをすることで、足に自分を撃ってしまうのは何ですか? –

+0

上記の説明を目的としています...ポイントは、リソースが空いているときに使用することです...そして上記の問題は、プール内の10の接続も引き続き発生します – Bhuvan

+0

いいえ、十分な接続があればプールに。私は本当にあなたが人工的な問題の解決策を探していると思います。 –

答えて

0

異なるスレッドからのトランザクションを1つのJDBC接続に多重化することはできません。たとえJTA仕様でこれが可能であると言われても、実際にはこれは起こらず、JDBCドライバは同期しています。

いずれも1)と2)とあなたのニーズに適した提案はありません。

  1. トランザクションの境界を自分で管理するのではなく、基盤となるプラットフォームのトランザクションサポート(Java EE、Springなど)を使用する必要があります。
  2. after_statementincurs some penaltyですが、それでもトランザクションは接続にバインドされます。だから、

、実行可能な選択肢は以下のとおりです。データベース接続あたりのトランザクションの多くを実行できるように

  1. は、できるだけ多くのトランザクション時間を削減します。
  2. マスタスレーブデータベースレプリケーションを使用して読み取り専用接続を増やし、読み取り専用トランザクションをスレーブにルーティングします。
+1

'とJDBCドライバは同期しています。 '私はそれを疑う... https://jdbc.postgresql.org/documentation/91/thread.htmlは' PostgreSQL™JDBCドライバはスレッドセーフである 'と述べている – Bhuvan

+1

さて、あなたが私に送ったリンクの第3段落はどうですか?スレッドが接続を使用していて、別のスレッドもそのスレッドを使用したい場合は、最初のスレッドが終了するまで待機します。これは多重化のように聞こえますか?それとも同期実行ですか? –

+1

あなたは正しいです。しかし、3番目の段落の2番目の文を読んだ場合、現在のクエリを完了した直後に接続が次の操作に移動することを意味し、異なる読み込みクエリを多重化すると、 hibernateはそのクエリの結果を処理しています。 – Bhuvan

関連する問題