この章では、次の項目について説明します。
多くの場合、アプリケーションは、接続プールから取得した接続を使用する前に初期化します。初期化は一様ではなく、アプリケーション・コード内でメソッド・コールを必要とする単純な状態の再初期化や、ネットワーク上でのラウンドトリップを必要とするデータベース操作などがあります。このような初期化のコストは非常に高い場合があります。
接続のラベル付けを使用すると、アプリケーションが接続に任意の名前/値のペアを付けることができます。アプリケーションは、必要なラベルが付いた接続を接続プールにリクエストできます。特定のラベルと特定の接続状態を関連付けることで、すでに初期化されている接続をプールから取得し、再初期化の時間とコストを回避できます。接続ラベリング機能は、ユーザー定義キーまたは値に意味を与えません。ユーザー定義キーおよび値の意味は、アプリケーションでのみ定義されます。
接続ラベリングの例には、ロール、NLS言語設定、トランザクション分離レベル、ストアド・プロシージャ・コール、またはリソースによる処理の実行の前に接続上で必要となるその他のコストのかかる状態の初期化があります。
接続ラベリングはアプリケーション駆動型で、2つのインタフェースを使用する必要があります。oracle.ucp.jdbc.LabelableConnection
インタフェースは、接続ラベルの適用および削除と、接続に設定されているラベルの取得に使用されます。oracle.ucp.ConnectionLabelingCallback
インタフェースは、リクエストされたラベルが付いた接続がすでに存在するかどうかを判断するラベリング・コールバックの作成に使用されます。接続が存在しない場合、このインタフェースを使用して、現行の接続を必要に応じて構成できます。これらのインタフェースのメソッドについては、この章全体を通して詳しく説明します。
UCPは、単一のラベルまたは複数のラベルの使用に関係なく、データベース常駐接続プーリング(DRCP)・タグ付けインフラストラクチャを使用して、UCPのラベリングをサポートします。ただし、UCPのみのかわりにUCPおよびDRCPの組合せを使用する場合、複数のラベルを使用した動作は少し異なる可能性があります。
ラベリング・コールバックは、接続プールでラベル付けされた接続を選択する方法を定義するために使用され、アプリケーションに戻す前に、選択された接続の構成ができます。接続ラベリング機能を使用するアプリケーションは、コールバックを実装する必要があります。
ラベリング・コールバックは、ラベル付けされた接続がリクエストされていながら、リクエストされたラベルと一致する接続がプールにない場合に使用されます。コールバックは、リクエストされたラベルと一致するように再構成するために必要となる作業量が最も少ない接続を特定した後、アプリケーションに戻す前に接続ラベルを更新できるようにします。この項の内容は次のとおりです。
ラベリング・コールバックを作成するために、アプリケーションはoracle.ucp.ConnectionLabelingCallback
インタフェースを実装します。コールバックは、接続プールごとに1つ作成されます。インタフェースでは、次の2つのメソッドが提供されています。
このメソッドは、ラベルマッチングの相違を考慮に入れて、接続の構成コストを見積ります。接続リクエストが発生すると、接続プールはこのメソッドを使用して、最も構成コストが低い接続を選択します。
public int cost(Properties requestedLabels, Properties currentLabels);
このメソッドは、アプリケーションに戻す前に、選択された接続に対して接続プールによってコールされます。接続の状態を設定し、接続に対してラベルの適用または削除を行うために、このメソッドが使用されます。
public boolean configure(Properties requestedLabels, Connection conn);
接続プール内で使用可能な各接続に対して繰り返します。接続ごとにcost
メソッドをコールします。cost
メソッドの結果は、接続を必要な状態に再構成するために必要なコストの見積りを表すinteger
です。値が大きいほど、接続の再構成にはコストがかかります。接続プールは、常に最も低いコスト値の接続を戻します。アルゴリズムは次のとおりです。
cost
メソッドがある接続について0
を戻した場合、その接続が適合となります。接続プールは、検出された接続に対してconfigure
メソッドをコールせず、その接続をそのまま戻します。
cost
メソッドが0
より大きい値を戻した場合、コスト値が0
の接続を検出するか、使用可能な接続がなくなるまで繰り返します。
すべての使用可能な接続に対して繰り返して、接続の最低コストがInteger.MAX_VALUE
(デフォルトでは2147483647)となった場合、プール内に接続リクエストを満たす接続はありません。プールは新しい接続を作成して戻します。プールが最大プール・サイズに達している(新しい接続を作成できない)場合は、SQL例外をスローするか、接続待機タイムアウト属性が指定されていれば待機するかのいずれかです。
すべての使用可能な接続に対して繰り返して、接続の最低コストがInteger.MAX_VALUE
よりも低い場合、その接続に対してconfigure
メソッドをコールし、その接続を戻します。複数の接続がInteger.MAX_VALUE
を下回る場合は、最低コストの接続を戻します。
注意: コスト0 は、requestedLabels とcurrentLabels が等しいという意味ではありません。 |
次の例では、cost
とconfigure
の両メソッドを実装する単純なラベリング・コールバックの実装を示します。このコールバックは、特定のトランザクション分離レベルで初期化されるラベル付けされた接続の検出に使用されます。
class MyConnectionLabelingCallback implements ConnectionLabelingCallback { public MyConnectionLabelingCallback() { } public int cost(Properties reqLabels, Properties currentLabels) { // Case 1: exact match if (reqLabels.equals(currentLabels)) { System.out.println("## Exact match found!! ##"); return 0; } // Case 2: some labels match with no unmatched labels String iso1 = (String) reqLabels.get("TRANSACTION_ISOLATION"); String iso2 = (String) currentLabels.get("TRANSACTION_ISOLATION"); boolean match = (iso1 != null && iso2 != null && iso1.equalsIgnoreCase(iso2)); Set rKeys = reqLabels.keySet(); Set cKeys = currentLabels.keySet(); if (match && rKeys.containsAll(cKeys)) { System.out.println("## Partial match found!! ##"); return 10; } // No label matches to application's preference. // Do not choose this connection. System.out.println("## No match found!! ##"); return Integer.MAX_VALUE; } public boolean configure(Properties reqLabels, Object conn) { try { String isoStr = (String) reqLabels.get("TRANSACTION_ISOLATION"); ((Connection)conn).setTransactionIsolation(Integer.valueOf(isoStr)); LabelableConnection lconn = (LabelableConnection) conn; // Find the unmatched labels on this connection Properties unmatchedLabels = lconn.getUnmatchedConnectionLabels(reqLabels); // Apply each label <key,value> in unmatchedLabels to conn for (Map.Entry<Object, Object> label : unmatchedLabels.entrySet()) { String key = (String) label.getKey(); String value = (String) label.getValue(); lconn.applyConnectionLabel(key, value); } } catch (Exception exc) { return false; } return true; } }
プール対応のデータソースは、ラベリング・コールバックを登録するためのregisterConnectionLabelingCallback(ConnectionLabelingCallback callback)
メソッドを備えています。1つの接続プールに登録できるコールバックは1つのみです。次の例では、MyConnectionLabelingCallback
クラスに実装されているラベリング・コールバックの登録を示します。
MyConnectionLabelingCallback callback = new MyConnectionLabelingCallback(); pds.registerConnectionLabelingCallback( callback );
DRCPは、重みのない単一のラベルである接続のタグ付けをネイティブにサポートします。そのため、DRCPでUCPを使用する場合、単一のラベルを使用したラベル付けは透過的に動作します。複数のラベルのUCP接続は動作しますが、次の動作変更があります。
接続ラベリングを使用してDRCPでUCPを使用する場合、ConnectionLabelingCallback
APIのcost
メソッドは起動しません。
UCPは、DRCP構成なしではなくDRCP構成ありでConnectionLabelingCallback
APIのconfigure
メソッドを起動できます。
関連項目: DRCPの詳細は、『Oracle Database JDBC開発者ガイド』を参照してください。 |
ラベルは、LabelableConnection
インタフェースのapplyConnectionLabel
メソッドを使用して、流用された接続に適用されます。通常、このメソッドは、ラベリング・コールバックのconfigure
メソッドからコールされます。任意の数の接続ラベルを流用された接続に累積的に適用できます。ラベルが接続に適用されるたびに、指定されたキー/値のペアが、すでに接続に適用されているラベルのコレクションに追加されます。最後に適用された値のみがどのキーに対しても保持されます。
注意: 流用された接続にラベルを適用するには、ラベリング・コールバックを接続プールに登録する必要があります。登録しないと例外がスローされます。「UCPでのラベリング・コールバックの実装」を参照してください。 |
次の例では、トランザクション分離レベルで接続を初期化した後、ラベルを接続に適用しています。
String pname = "property1"; String pvalue = "value"; Connection conn = pds.getConnection(); // initialize the connection as required. conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); ((LabelableConnection) conn).applyConnectionLabel(pname, pvalue);
特定のキーを適用済の接続ラベルのセットから削除するには、削除するキーおよびnull
値のラベルを適用します。この方法は、接続ラベルのセットから特定のキー/値ペアを消去するために使用できます。
プール対応のデータソースは、ラベル付けされた接続をプールから流用するために使用される2つのgetConnection
メソッドを備えています。これらのメソッドを次に示します。
public Connection getConnection(java.util.Properties labels ) throws SQLException; public Connection getConnection( String user, String password, java.util.Properties labels ) throws SQLException;
これらのメソッドには、getConnection
メソッドにProperties
オブジェクトとして渡すラベルが必要です。次の例では、property1, value
というラベルが付いた接続の取得を示します。
String pname = "property1"; String pvalue = "value"; Properties label = new Properties(); label.setProperty(pname, pvalue); Connection conn = pds.getConnection(label);
1つの接続は複数のラベルを保有できます。各ラベルは目的とする条件に基づいて一意に接続を識別します。getUnmatchedConnectionLabels
メソッドは、リクエストされたラベルから、どの接続ラベルが一致してどの接続ラベルが一致しなかったかを検証するために使用されます。このメソッドは、複数のラベルを持つ接続が接続プールから流用された後に使用され、通常、ラベリング・コールバックで使用されます。次の例では、不一致ラベルのチェックを示します。
String pname = "property1"; String pvalue = "value"; Properties label = new Properties(); label.setProperty(pname, pvalue); Connecion conn = pds.getConnection(label); Properties unmatched = ((LabelableConnection) connection).getUnmatchedConnectionLabels (label);
removeConnectionLabel
メソッドは、接続からラベルを削除するために使用されます。このメソッドは、ラベル付けされた接続が接続プールから流用された後に使用されます。次の例では、接続ラベルの削除を示します。
String pname = "property1"; String pvalue = "value"; Properties label = new Properties(); label.setProperty(pname, pvalue); Connection conn = pds.getConnection(label); ((LabelableConnection) conn).removeConnectionLabel(pname);