アプリケーションでのTimesTenの機能と操作

この項では、TimesTenデータベースでのデータの操作方法の詳細情報を説明します。

この項の内容は、次のとおりです。

文でのJavaラッパー機能の使用

TimesTenでは、標準のjava.sql.Wrapper機能を介してTimesTen固有の実装を公開します。

Wrapperを使用してTimesTenStatementTimesTenPreparedStatementおよびTimesTenCallableStatementインタフェースを実装する文オブジェクトを取得し、TimesTen固有の機能にアクセスできるようにできます。類似する説明、および接続オブジェクトに関する例は、「TimesTenデータベース接続の管理」を参照してください。

TimesTen結果セットの使用: ヒントおよび制限

この項では、TimesTenからのResultSetオブジェクトの使用について説明します。

ResultSetオブジェクトを使用して、問合せ結果を処理します。また、一部のメソッドおよび組込みプロシージャは、ResultSetオブジェクトの形式でTimesTenデータを返します。

ノート:

TimesTenでは、コミットやロールバックなど、トランザクションを終了する操作は、接続に関連付けられているすべてのカーソルをクローズします。

  • TimesTenでは、1つの文で複数のResultSetオブジェクトをオープンすることはできません。また、1つのStatementオブジェクトから、現行結果セットをクローズせずに複数のResultSetオブジェクトを返すことはできません。

  • TimesTenでは、保持可能なカーソルはサポートされていません。結果セットの保持可能性(つまり、カーソルのコミット後に、そのカーソルをオープンしたままにできるかどうか)は指定できません。

  • ResultSetオブジェクトをスクロールまたは更新できないため、ResultSet.TYPE_SCROLL_SENSITIVEまたはResultSet.CONCUR_UPDATABLEは指定できません。

  • 通常は、ResultSetメソッドclose()を使用して、処理後すぐに結果セットをクローズできます。パフォーマンス上の理由から、これは読取りおよび更新処理で使用される結果セットおよびプール接続で使用される結果セットで特に重要です。

    TimesTen結果セットはまた、java.lang.AutoCloseableを使用した標準のtry-with-resource機能もサポートしています。

  • 基礎となるデータ型が文字列ではない場合、ResultSetメソッドgetString()をコールすると、パフォーマンスの点でコストが高くなります。Javaの文字列は不変的であるため、getString()は、コールされるたびに新しい文字列用に領域を確保する必要があります。したがって、必要な場合を除き、byteintなどの基本的な数値型の取得にgetString()を使用しないでください。たとえば、整数列の場合、getInt()をコールする方が大幅に高速に処理が実行されます。「ResultSetのメソッドgetString()の使用は慎重に」も参照してください。

    また、日付およびタイムスタンプの場合、ResultSetのネイティブ・メソッドgetDate()およびgetTimestamp()の方がgetString()よりもパフォーマンスに優れています。

  • getXXX()コールの選択および起動後の必要なデータ変換は、アプリケーション・パフォーマンスに影響を与えます。

  • JDBCはConnectionCharacterSet属性の設定を無視します。データはUTF-16エンコードで返されます。

複数のデータ行のフェッチ

複数のデータ行をフェッチすると、コミット読取り分離レベルが設定されたデータベースに接続しているクライアント/サーバー・アプリケーションのパフォーマンスを向上させることができます。

この項では、TimesTenで実装されている接続レベルのプリフェッチについて説明します。

プリフェッチする行数を指定するには、TimesTenConnectionメソッドsetTtPrefetchCount()をコールします。これにより、ある接続に対するすべての文で同じプリフェッチ設定が使用されるように、その接続レベルでのプリフェッチを確立するTimesTenの拡張が有効になります。

ノート:

TimesTenのプリフェッチ数を拡張しても、データベースへの直接接続を使用するアプリケーションにとってメリットはありません。

プリフェッチ数を0(ゼロ)に設定すると、TimesTenはデータベースに設定した分離レベルに応じてデフォルトのプリフェッチ数を使用し、プリフェッチ数をその値に設定します。コミット読取り分離レベルでは、デフォルトのプリフェッチの値は5です。シリアライズ可能分離レベルでは、デフォルトは128です。デフォルトのプリフェッチの値はほとんどのアプリケーションに最適な設定です。一般的に、値を高く設定すると、リソースの使用量がわずかに増加しますが、大きい結果セットに対するパフォーマンスは向上する可能性があります。

プリフェッチを無効にするには、プリフェッチ数を1に設定します。

TimesTenConnectionメソッドgetTtPrefetchCount()をコールして、現行のプリフェッチ値を確認します。

「java.sqlパッケージ内のインタフェースのサポート」Connectionインタフェース項目を参照してください。Oracle TimesTen In-Memory Database JDBC拡張機能Java APIリファレンスを参照してください。

次の例では、setTtPrefetchCount()コールを使用して、プリフェッチ数を10に設定し、getTtPrefetchCount()コールを使用して、カウント変数のプリフェッチ数を返します。

TimesTenConnection conn =
    (TimesTenConnection) DriverManager.getConnection(url);

// set prefetch count to 10 for this connection
conn.setTtPrefetchCount(10);

// Return the prefetch count to the 'count' variable.
int count = conn.getTtPrefetchCount();

問合せのパフォーマンスの最適化

TimesTen拡張機能を使用すると、アプリケーションでは、trueを設定してTimesTenConnectionメソッドのsetTtPrefetchClose()をコールすることにより、クライアント/サーバー・アプリケーションの読取り専用問合せのパフォーマンスを最適化できます。

すべてのトランザクションは、読取り専用トランザクションを含め、実行時にコミットされる必要があります。setTtPrefetchClose(true)コールでは、サーバーはカーソルを自動的にクローズして、サーバーが読取り専用問合せの結果セットのすべての行をプリフェッチした後でトランザクションをコミットします。これによって、クライアントとサーバー間のネットワーク・ラウンドトリップ数が減少するため、パフォーマンスが向上します。

クライアントでは、依然として結果セットをクローズしてトランザクションをコミットする必要がありますが、これらのコールはクライアントで実行されるため、クライアントとサーバー間のネットワーク・ラウンドトリップを必要としません。

ノート:

  • setTtPrefetchClose(true)コールを使用した同じ接続に対して複数の文ハンドルを使用しないでください。サーバーでは、クライアントが終了する前に、結果セットのすべての行がフェッチされ、トランザクションがコミットされて文ハンドルがクローズされる可能性があります。これにより、すべての文ハンドルが閉じられます。

  • TimesTen直接接続およびSELECT FOR UPDATE文の場合、true設定は無視されます。

  • getTtPrefetchClose()を使用して、現在の設定(trueまたはfalse)を取得します。

次の例に、setTtPrefetchClose(true)の使用方法を示します。

import com.timesten.sql;
...
con = DriverManager.getConnection ("jdbc:timesten:client:" + DSN);
stmt = con.createStatement();
...
con.setTtPrefetchClose(true);
rs = stmt.executeQuery("select * from t");
while(rs.next())
{
// do the processing
}
rs.close();
con.commit();

パラメータのバインドと文の実行

ここでは、SQL文の入力または出力パラメータをバインドする方法について説明します。

内容は次のとおりです。

ノート:

TimesTen開発者ガイドで使用される「バインド・パラメータ」という用語(ODBC用語に準拠)は、TimesTenのPL/SQLのマニュアルで使用される「バインド変数」という用語(Oracle Database PL/SQL用語に準拠)と同じです。

SQL文の準備および入力パラメータの設定

複数回実行するSQL文は、ConnectionメソッドprepareStatement()をコールして事前に準備しておく必要があります。最大のパフォーマンスを得るために、パラメータを使用した文を準備します。

次のことに注意してください。

  • TimesTenのバインド・メカニズム(アーリー・バインディング)はOracle Databaseのバインド・メカニズム(レイト・バインディング)とは異なります。TimesTenは、問合せの準備の前にデータ型を必要とします。そのため、各バインド・パラメータのデータ型が指定されていないかSQL文から推測できないと、エラーが発生します。たとえば次のような文が、これに該当します。

    SELECT 'x' FROM DUAL WHERE ? = ?;

    この問題には、たとえば次のように対処できます。

    SELECT 'x' from DUAL WHERE CAST(? as VARCHAR2(10)) = CAST(? as VARCHAR2(10));
  • デフォルトでは(接続属性PrivateCommands=0の場合)、TimesTenは接続間で準備された文を共有するため、様々な接続での同じ文の後続の準備は非常に迅速に実行されます。

  • setXXX()コールの選択および起動前の必要なデータ変換は、アプリケーション・パフォーマンスに影響を与えます。たとえば、時刻、日付およびタイムスタンプでは、PreparedStatementのネイティブ・メソッドsetTime()setDate()およびsetTimestamp()は、setString()よりもパフォーマンスに優れています。

  • TT_TINYINT列では、TT_TINYINT (0から255)の範囲を完全に使用するために、setByte()のかわりにsetShort()またはsetInt()を使用します。

  • setObject(java.util.Calendar)およびsetDate(java.util.Date)を使用した設定はTIMESTAMPにマップされます。

次の例では、PreparedStatementオブジェクトでの基本的なexecuteQuery()コールを示します。これは、準備済のSELECT文を実行して、返された結果セットを表示します。

PreparedStatement pSel = conn.prepareStatement("select cust_num, " +
                         "region, name, address " +
                         "from customer" +
                         "where region = ?");
pSel.setInt(1,1);

try {
  ResultSet rs = pSel.executeQuery();

  while (rs.next()) {
    System.out.println("\n Customer number: " + rs.getInt(1));
    System.out.println(" Region: " + rs.getString(2));
    System.out.println(" Name: " + rs.getString(3));
    System.out.println(" Address: " + rs.getString(4));
  }
} 
catch (SQLException ex) {
   ex.printStackTrace();
}

次の例に、4つの別々の文のかわりに、パラメータを使用した単一の文を使用する方法を示します。

値が異なる同様のINSERT文の実行:

Statement.execute("insert into t1 values (1, 2)");
Statement.execute("insert into t1 values (3, 4)");
Statement.execute("insert into t1 values (5, 6)");
Statement.execute("insert into t1 values (7, 8)");

パラメータを使用した単一のINSERT文を準備し、PreparedStatementメソッドsetXXX()を使用して、各文を実行する前に行の値を設定する方がより効率的です。

PreparedStatement pIns = conn.PreparedStatement("insert into t1 values (?,?)");

pIns.setInt(1, 1);
pIns.setInt(2, 2);
pIns.executeUpdate();

pIns.setInt(1, 3);
pIns.setInt(2, 4);
pIns.executeUpdate();

pIns.setInt(1, 5);
pIns.setInt(2, 6);
pIns.executeUpdate();

pIns.setInt(1, 7);
pIns.setInt(2, 8);
pIns.executeUpdate();

conn.commit();
pIns.close();

TimesTenでは、準備済の文はコミットされると自動的に共有されます。たとえば、データベースへの2つ以上の別々の接続が、それぞれ同じ文を、1個、2個、3個、...、n個準備した場合、TimesTenは最初に準備した文を覚えているため、n番目の準備はとても早く返されます。

次の例では、INSERT文とSELECT文を準備し、INSERTを2回実行し、SELECTを実行し、返された結果セットを出力します。実際の例については、level1サンプル・アプリケーションを参照してください。(サンプル・アプリケーションについては、「TimesTenクイック・スタートおよびサンプル・アプリケーションについて」を参照してください。)

Connection conn = null;
...
// [Code to open connection. See Connecting to the Database...]
...

// Disable auto-commit
conn.setAutoCommit(false);

    // Report any SQLWarnings on the connection
    // See Reporting Errors and Warnings

// Prepare a parameterized INSERT and a SELECT Statement
PreparedStatement pIns = 
                  conn.prepareStatement("insert into customer values (?,?,?,?)");

PreparedStatement pSel = conn.prepareStatement
    ("select cust_num, region, name, " +
    "address from customer");

// Data for first INSERT statement
pIns.setInt(1, 100);
pIns.setString(2, "N");
pIns.setString(3, "Fiberifics");
pIns.setString(4, "123 any street");

// Execute the INSERT statement
pIns.executeUpdate();

// Data for second INSERT statement
pIns.setInt(1, 101);
pIns.setString(2, "N");
pIns.setString(3, "Natural Foods Co.");
pIns.setString(4, "5150 Johnson Rd");

// Execute the INSERT statement
pIns.executeUpdate();

// Commit the inserts
conn.commit();

// Done with INSERTs, so close the prepared statement
pIns.close();

// Report any SQLWarnings on the connection. 
reportSQLWarnings(conn.getWarnings());

// Execute the prepared SELECT statement
ResultSet rs = pSel.executeQuery();

System.out.println("Fetching result set...");
while (rs.next()) {
    System.out.println("\n Customer number: " + rs.getInt(1));
    System.out.println(" Region: " + rs.getString(2));
    System.out.println(" Name: " + rs.getString(3));
    System.out.println(" Address: " + rs.getString(4));
}

// Close the result set.
rs.close();

// Commit the select - yes selects must be committed too
conn.commit();

// Close the select statement - we are done with it
pSel.close();

次の例では、3つの接続に対して、パラメータを使用した同一のINSERT文を3つ準備します。接続conn1の最初の準備済INSERTは、TimesTen内部の準備済文キャッシュ内でconn2およびconn3接続と共有され、pIns2およびpIns3の準備操作を加速します。

Connection conn1 = null;
Connection conn2 = null;
Connection conn3 = null;
.....
PreparedStatement pIns1 = conn1.prepareStatement
                  ("insert into t1 values (?,?)");

PreparedStatement pIns2 = conn2.prepareStatement
                  ("insert into t1 values (?,?)");

PreparedStatement pIns3 = conn3.prepareStatement
                  ("insert into t1 values (?,?)");

ノート:

結合順序、索引、ロックなど、すべてのオプティマイザ・ヒントは、TimesTenの内部準備済文キャッシュで共有される文と一致している必要があります。また、準備された文が一時表を参照する場合、この文は1つの接続内でのみ共有されます。

出力および入力/出力パラメータの使用

文を準備し、PreparedStatementメソッドを使用して入力パラメータを設定できます。

「SQL文の準備および入力パラメータの設定」を参照してください。TimesTenでは、PreparedStatementのかわりにjava.sql.CallableStatementを使用する、次の出力および入力/出力パラメータもサポートしています。

  1. メソッドregisterOutParameter()を使用して、出力パラメータまたは入力/出力パラメータを登録し、パラメータの位置(文内の位置)およびデータ型を指定します。

    これは、CallableStatementインタフェースで指定されている標準のメソッドです。

    void registerOutParameter(int parameterIndex, int sqlType, int scale)

    ただし、CHARVARCHARNCHARNVARCHARBINARYまたはVARBINARYデータに対してこの標準バージョンを使用すると、TimesTenでは、指定可能な最大値を保持するために必要なメモリーを割り当てます。これは、ほとんどの場合で無駄になります。

    そのかわりに、最大データ長を指定できるregisterOutParameter()シグネチャが含まれるTimesTenの拡張インタフェースTimesTenCallableStatementを使用します。CHARVARCHARNCHARおよびNVARCHARについては、長さの単位は文字数になります。BINARYおよびVARBINARYについてはバイトになります。

    void registerOutParameter(int paramIndex,
                              int sqlType,
                              int ignore, //This parameter is ignored by TimesTen.
                              int maxLength)
  2. 適切なCallableStatementメソッドsetXXX()を使用し(XXXはデータ型を示します)、入力/出力パラメータの入力値を設定します。パラメータの位置およびデータの値を指定します。

  3. 適切なCallableStatementメソッドgetXXX()を使用して、出力パラメータまたは入力/出力パラメータの出力値を取得し、パラメータの位置を指定します。

ノート:

  • 出力パラメータを処理する前にSQL警告を確認します。警告イベント中には、出力パラメータは定義されません。「エラー処理」を参照してください。

  • 名前を使用してパラメータをCallableStatementオブジェクトに渡すことはできません。位置でパラメータを設定する必要があります。SQLのエスケープ構文は使用できません。

  • 名前によってパラメータを指定するregisterOutParameter()シグネチャはサポートされていません。位置によってパラメータを指定する必要があります。

  • SQL構造型はサポートされていません。

この例は、コール可能な文での出力パラメータの使用方法を示します。TimesTenCallableStatementインスタンスで、PL/SQLブロックは、新しい給与を計算し、整数で返すファンクションRAISE_SALARYをコールします。Connectionインスタンスをconnとします。(『Oracle TimesTen In-Memory Database PL/SQL開発者ガイド』PL/SQL機能の概要を参照してください。)

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Types;
import com.timesten.jdbc.TimesTenCallableStatement;
...
// Prepare to call a PL/SQL stored procedure RAISE_SALARY
CallableStatement cstmt = conn.prepareCall
                          ("BEGIN :newSalary := RAISE_SALARY(:name, :inc); end;");
      
// Declare that the first param (newSalary) is a return (output) value of type int
cstmt.registerOutParameter(1, Types.INTEGER);
 
// Raise Leslie's salary by $2000 (who wanted $3000 but we held firm)
cstmt.setString(2, "LESLIE"); // name argument (type String) is the second param
cstmt.setInt(3, 2000); // raise argument (type int) is the third param
 
// Do the raise
cstmt.execute();

// Check warnings. If there are warnings, output parameter values are undefined.
SQLWarning wn;
boolean warningFlag = false;
if ((wn = cstmt.getWarnings() ) != null) {
   do {
        warningFlag = true;
        System.out.println(wn);
        wn = wn.getNextWarning();
   } while(wn != null);
}      
      
// Get the new salary back
if (!warningFlag) {
   int new_salary = cstmt.getInt(1);
   System.out.println("The new salary is: " + new_salary);
}

// Close the statement and connection
cstmt.close();
conn.close();
...

SQL文での重複したパラメータのバインド

TimesTenでは、1つのSQL文に同じパラメータ名が複数出てきた場合は異なるパラメータとみなされます。(これは、Oracle Databaseによる重複パラメータのバインディングのサポートに準拠しています。)

ノート:

  • この説明は、PL/SQL経由などではなく、ODBCから直接発行されるSQL文にのみ当てはまります。

  • 重複したパラメータをバインディングする「TimesTenモード」、およびDuplicateBindMode接続属性は非推奨となっています。

次の問合せについて考えてみましょう:

SELECT * FROM employees
  WHERE employee_id < :a AND manager_id > :a AND salary < :b;

パラメータ位置番号を割り当てるとき、名前の重複は考慮せずに各パラメータの出現に番号が割り当てられます。アプリケーションでは、最低でも、各パラメータ名の最初の出現に値がバインドされます。そのパラメータ名が次回出現した場合、アプリケーションでは次のいずれかが実行されます。

  • その出現に対して別の値をバインドします。

  • そのパラメータの出現をバインドしないままにします。この場合は、最初の出現と同じ値をとります。

どちらの場合でも、それぞれの出現は、異なるパラメータ位置番号を持っています。

前述のSQL文で、aの2度目の出現に対して別の値を使用するには、次のようにします。

pstmt.setXXX(1, ...); /* first occurrence of :a */
pstmt.setXXX(2, ...); /* second occurrence of :a */
pstmt.setXXX(3, ...); /* occurrence of :b */

両方のaの出現に対して同じ値を使用するには、次のようにします。

pstmt.setXXX(1, ...); /* both occurrences of :a */
pstmt.setXXX(3, ...); /* occurrence of :b */

いずれの場合も、パラメータbは位置3にあるとみなされます。

PL/SQLでの重複したパラメータのバインド

前述の説明は、独自のセマンティクスがあるPL/SQLには該当しません。PL/SQLでは、一意の各パラメータ名に値をバインドします。

たとえば、次のブロックを実行するアプリケーションは、:aに対応する1つのパラメータのみをバインドします。

DECLARE
   x NUMBER;
   y NUMBER;
BEGIN
   x:=:a;
   y:=:a;
END;

次のブロックを実行するアプリケーションでも、1つのパラメータのみをバインドします。

BEGIN
   INSERT INTO tab1 VALUES(:a, :a);
END

これは、次のCALL文でも同様です。

...CALL proc(:a, :a)...

次のブロックを実行するアプリケーションは、2つのパラメータ(パラメータ#1に:a、パラメータ#2に:b)をバインドします。各INSERT文の2番目のパラメータは、次のように、最初のINSERT文の最初のパラメータと同じ値を使用します。

BEGIN
   INSERT INTO tab1 VALUES(:a, :a);
   INSERT INTO tab1 VALUES(:b, :a);
END

連想配列の使用

この項では、TimesTenで連想配列をバインドして使用する方法について説明します。

連想配列の概要

TimesTen JDBCでは、TimesTen PL/SQLへのINOUTまたはIN OUTバインド・パラメータである、以前の索引付き表またはPL/SQL表と呼ばれていた連想配列バインドをサポートしています。連想配列では、JDBCアプリケーションとデータベース間で効率的にデータの配列を渡すことを可能にします。

連想配列とは、キーと値のペアのセットです。TimesTenの連想配列バインド(PL/SQL内のみに連想配列の使用は限定されません)では、キーまたは索引は整数(BINARY_INTEGERまたはPLS_INTEGER)である必要があります。値は、同じデータ型のスカラー値である必要があります。たとえば、部署番号ごとに索引付された部署のマネージャの配列を作成できます。索引は、作成された順序ではなく、ソートされた順序で格納されます。

次の例のように、PL/SQLで連想配列型を宣言した後、連想配列を宣言します(INDEX BYに注意してください)。

declare
   TYPE VARCHARARRTYP IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER;
   x VARCHARARRTYP;
   ...

『Oracle TimesTen In-Memory Database PL/SQL開発者ガイド』アプリケーションからの連想配列の使用も参照してください。

ノート:

  • 連想配列のバインドでは、LOB、REF CURSOR、TIMESTAMPROWIDの型はサポートされていません。

  • パススルー文では連想配列のバインドはサポートされていません。

  • TimesTenのJDBCでは、一般的な配列のバルク・バインドはサポートされていません。VARRAYおよびネストされた表は、バインド・パラメータとしてサポートされていません。

  • 連想配列パラメータは、JDBCのバッチの実行ではサポートされていません(「バッチ実行にパラメータの配列を使用」を参照してください)。

連想配列のTimesTenメソッド

TimesTenには、TimesTenPreparedStatementTimesTenCallableStatementのインタフェースを介して連想配列のバインドをサポートする拡張が用意されています。

ここで説明するメソッドの詳細は、Oracle TimesTen In-Memory Database JDBC拡張Java APIリファレンスを参照してください。

TimesTenでは、PL/SQLのINまたはIN OUTパラメータである連想配列で入力連想配列を設定するために、(INパラメータ用に)TimesTenPreparedStatementインタフェースで、また(IN OUTパラメータ用に)TimesTenCallableStatementインタフェースで、setPlsqlIndexTable()メソッドを用意しています。

  • void setPlsqlIndexTable(int paramIndex, java.lang.Object arrayData, int maxLen, int curLen, int elemSqlType, int elemMaxLen)

    次のように指定します:

    • paramIndex: (1で開始する)PL/SQL文内のパラメータの位置

    • arrayData: バインドする値の配列(これはint[]などプリミティブ型の配列またはBigDecimal[]などオブジェクト型の配列が許可されます)

    • maxLen: 連想配列内の要素の最大数(TimesTenでは、curLenと同じにする必要があります)

    • curLen: 連想配列内に現在ある要素の実際の数(TimesTenではmaxLenと同じである必要があります)

    • elemSqlType: java.sql.Typesと一致する連想配列の要素の型(Types.DOUBLEなど)

    • elemMaxLen: CHARVARCHARBINARYまたはVARBINARYの連想配列で、各要素の最大長(CHARまたはVARCHARの連想配列では文字、BINARYまたはVARBINARYの連想配列ではバイトです)

    たとえば (TimesTenPreparedStatementインスタンスpstmtを仮定):

    int maxLen = 3;
    int curLen = 3;
    // Numeric field can be set with int, float, double types.
    // elemMaxLen is set to 0 for numeric types and is ignored.
    // elemMaxLen is specified for VARCHAR types.
    pstmt.setPlsqlIndexTable
          (1, new int[]{4, 5, 6}, maxLen, curLen, Types.NUMERIC, 0);
    pstmt.setPlsqlIndexTable
          (2, new String[]{"Batch1234567890", "2", "3"}, maxLen, curLen,
           Types.VARCHAR, 15);
    pstmt.execute();

ノート:

  • elemMaxLenパラメータは、CHARVARCHARBINARYまたはVARBINARY以外の型では無視されます。それらのすべての型では、値に0を使用すると、バインドされているデータの実際の長さに基づいて各要素の最大長を設定するようドライバに指示できます。elemMaxLenが正の値に設定され、実際のデータ長がelemMaxLenより大きい場合、データは常にelemMaxLenの長さに切り捨てられます。

  • curLenが連想配列内の実際の要素数より小さい場合、curLenの要素のみがバインドされます。

TimesTenでは、PL/SQLのOUTまたはIN OUTパラメータである連想配列用に、出力連想配列を登録するregisterIndexTableOutParameter()と出力連想配列を取得するgetPlsqlIndexTable()の2つのメソッドをTimesTenCallableStatementインタフェースに用意しています。getPlsqlIndexTable()には、連想配列の要素がSQL型であると仮定しJDBCのデフォルトのJavaオブジェクト型を使用するものと、型を指定する2つのシグネチャがあります。

  • void registerIndexTableOutParameter(int paramIndex, int maxLen, int elemSqlType, int elemMaxLen)

    次のように指定します:

    • paramIndex: (1で開始する)PL/SQL文内のパラメータの位置

    • maxLen: 連想配列に含めることが可能な要素の最大数

    • elemSqlType: java.sql.Typesと一致する連想配列の要素の型(Types.DOUBLEなど)

    • elemMaxLen: CHARVARCHARBINARYまたはVARBINARYの連想配列で、各要素の最大長(CHARまたはVARCHARの連想配列では文字、BINARYまたはVARBINARYの連想配列ではバイトです)

    ノート:

    elemMaxLenの値が0以下の場合、データ型の最大長が使用されます。

  • java.lang.Object getPlsqlIndexTable(int paramIndex)

    このメソッド・シグネチャでは、返された連想配列の型が、取得したSQL型のデータのJDBCでのデフォルトのマッピングになります。(1で開始する)PL/SQL文内のパラメータの位置を指定します。表2-4を参照してください。

  • java.lang.Object getPlsqlIndexTable(int paramIndex, java.lang.Class primitiveType)

    このメソッド・シグネチャでは、パラメータの位置の指定に加え、java.sql.Typesと一致する返される連想配列の希望の型を指定します(Types.DOUBLEなど)。これはプリミティブ型である必要があります。

連想配列の型マッピング

Javaで連想配列をバインドする場合、配列の型とできるだけ近いJavaの型を使用すると最適なパフォーマンスが得られます。ただし、TimesTenでは、特定の入力変換がサポートされています。

  • 文字列は整数または浮動小数点に変換できます。

  • 文字列がTimesTenのDATE(YYYY-MM-DD HH:MI:SS)の書式に従っている場合、文字列をDATEデータに変換できます。

表2-4に、連想配列要素のJDBCのデフォルト・マッピングを示します。

表2-4 連想配列要素のJDBCデフォルト・マッピング

戻り値の型 SQLの型

Integer[]

TINYINTSMALLINTTT_INTEGER

Long[]

BIGINT

BigDecimal[]

NUMBER

Float[]

BINARY_FLOAT

Double[]

BINARY_DOUBLE

String[]

CHARVARCHARNCHARNVARCHAR

Timestamp[]

DATE

連想配列のバインド

次のコード部分では、IN OUTパラメータの内容を設定、登録および取得する方法を示しています(connは接続、cstmtTimesTenCallableStatementインスタンスを想定しています)。

int maxLen = 3;
int curLen = 3;
anonBlock = "begin AssocArrayEx_inoutproc(:o1); end;";
cstmt = (TimesTenCallableStatement) conn.prepareCall(anonBlock); 
cstmt.setPlsqlIndexTable
     (1, new Integer[] {1,2,3}, maxLen, curLen, Types.NUMERIC, 0);
cstmt.registerIndexTableOutParameter(1, maxLen, Types.NUMERIC, 0);
cstmt.execute();
 
int[]  ret = (int [])cstmt.getPlsqlIndexTable(1, Integer.TYPE);
cstmt.execute();

次の例はより完全な例で、連想配列のバインドのメカニズムを示しています。

    TimesTenCallableStatement cstmt = null;
    try {
      // Prepare procedure with associative array in parameter
      cstmt = (TimesTenCallableStatement) 
               conn.prepareCall("begin AssociativeArray_proc(:name, :inc); end;");
      
      // Set up input array and length
      String[] name = {"George", "John", "Thomas", "James", "Bill"};
      Integer[] salaryInc = {10000, null, 5000, 8000, 9007};
      int currentLen = name.length;
      int maxLen = currentLen;
 
      
      // Use elemMaxLen for variable length data types such as 
      // Types.VARCHAR, Types.CHAR.
      int elemMaxLen = 32; 
      
      // set input parameter, name as a VARCHAR
      cstmt.setPlsqlIndexTable 
            (1, name, maxLen, currentLen, Types.VARCHAR, elemMaxLen);
      // set input parameter, salaryInc as a number
      cstmt.setPlsqlIndexTable 
            (2, salaryInc, maxLen, currentLen, Types.NUMERIC, 0);

REF CURSORの使用

REF CURSORはPL/SQLの概念で、PL/SQLとアプリケーション間で受け渡しされるSQL結果セット上のカーソルに対するハンドルです。TimesTenでは、PL/SQL内でカーソルをオープンできるため、そのREF CURSORをアプリケーションに渡して結果セットを処理することができます。

TimesTenでは、標準のJDBC REF CURSORおよびTimesTen REF CURSORがサポートされています。

アプリケーションは、次のように、REF CURSOR OUTパラメータを受け取ることができます。

  1. CallableStatementメソッドregisterOutParameter()を使用して、REF CURSOR OUTパラメータをjava.sqlTypes.REF_CURSOR型として(標準のREF CURSORの場合)またはTimesTenTypes.CURSOR型として(TimesTen REF CURSORの場合)登録します。registerOutParameter()コールで、REF CURSORのパラメータ位置(文内の位置)を指定します。

  2. CallableStatementメソッドgetObject() (標準REF CURSORの場合)またはTimesTenCallableStatementメソッドgetCursor() (TimesTenREF CURSORの場合)を使用してREF CURSORを取得し、戻り値をResultSetとしてキャストします。REF CURSORのパラメータ位置を指定します。

TimesTen JDBC APIの詳細は、Oracle TimesTen In-Memory Database JDBC拡張Java APIリファレンスを参照してください。REF CURSORに関するその他の情報は、『Oracle TimesTen In-Memory Database PL/SQL開発者ガイド』PL/SQL REF CURSORを参照してください。

ノート:

PL/SQLとアプリケーションの間でREF CURSORを渡す場合、TimesTenでは、PL/SQLからアプリケーションへのOUTREF CURSORのみがサポートされます。

次の例では、コール可能な文でのTimesTen REF CURSORの使用方法を示し、次に標準のREF CURSORの使用方法を示します。

TimesTenのREF CURSOR:

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import com.timesten.jdbc.TimesTenCallableStatement;
import com.timesten.jdbc.TimesTenTypes;
...
Connection conn = null;
CallableStatement cstmt = null;
ResultSet cursor;
...
// Use a PL/SQL block to open the cursor.
cstmt = conn.prepareCall
             (" begin open :x for select tblname,tblowner from tables; end;");
cstmt.registerOutParameter(1, TimesTenTypes.CURSOR);
cstmt.execute();
cursor = ((TimesTenCallableStatement)cstmt).getCursor(1);

// Use the cursor as you would any other ResultSet object.
while(cursor.next()){
  System.out.println(cursor.getString(1));
}

// Close the cursor, statement, and connection.
cursor.close();
cstmt.close();
conn.close();
...

標準のREF CURSOR:

...
Connection conn = null;
CallableStatement cstmt = null;
ResultSet rs;
...
cstmt = conn.prepareCall
             (" begin open :x for select tblname,tblowner from tables; end;");
cstmt.registerOutParameter(1, Types.REF_CURSOR); 
cstmt.execute(); 
rs = cstmt.getObject(1, ResultSet.class);
while(rs.next()){
  System.out.println(rs.getString(1));
}

// Close the result set, statement, and connection.
rs.close();
cstmt.close();
conn.close();
...

ノート:

ループ内に様々なパラメータ値があるコール可能な文を評価する場合、ループの終了時には毎回カーソルをクローズする必要があります。文を準備した後にループにパラメータを設定し、文を実行し、カーソルを処理し、カーソルをクローズするのが標準的な使用法です。

DML RETURNING (RETURNING INTO句)の使用

DML RETURNINGと呼ばれるRETURNING INTO句をINSERTUPDATEまたはDELETE文で使用すると、処理の影響を受けた行の特定の項目を返すことができます。 これにより、たとえば処理によって影響を受けたものを確認する場合などで、続くSELECT文および個々のラウンド・トリップが不要になります。

TimesTenでは、DML RETURNINGは、単一行の操作から項目を戻すのみです。この句では、項目を出力パラメータのリストに返します。

TimesTenPreparedStatement(標準PreparedStatementインタフェースの拡張)は、DML RETURNINGをサポートします。TimesTenPreparedStatementメソッドregisterReturnParameter()を使用して、戻りパラメータを登録します。

void registerReturnParameter(int paramIndex, int sqlType)

「出力および入力/出力パラメータの使用」で説明したregisterOutParameter()メソッドと同様に、このメソッドには、CHARVARCHARNCHARNVARCHARBINARYまたはVARBINARYのデータにオプションで最大サイズを指定できるシグネチャがあります。これにより、TimesTenが非効率に設定可能な最大のメモリー値を割り当ててしまう可能性が回避されます。CHARVARCHARNCHARおよびNVARCHARのサイズ単位は、文字数です。BINARYおよびVARBINARYについてはバイトになります。

void registerReturnParameter(int paramIndex, int sqlType, int maxSize)

TimesTenPreparedStatementメソッドgetReturnResultSet()を使用して戻りパラメータを取得し、ResultSetインスタンスを返します。

TimesTen JDBCでRETURNING INTOを使用する場合は、次の制限に注意してください。

  • getReturnResultSet()メソッドは2回以上実行しないでください。実行すると、動作は不確定です。

  • getReturnResultSet()が返す結果セットは、ResultSetMetaDataをサポートしていません。

  • getReturnResultSet()が返す結果セットは、getCharacterStream()などのストリーミング・メソッドをサポートしていません。

  • DML RETURNINGをサポートするバッチはありません。

ここで説明するTimesTenのJDBCクラス、インタフェース、メソッドの詳細は、Oracle TimesTen In-Memory Database JDBC拡張Java APIリファレンスを参照してください。

『Oracle TimesTen In-Memory Database SQLリファレンス』内のINSERTUPDATEおよびDELETEの説明において、TimesTenでのRETURNING INTO句のSQL構文および制限事項が示されています。

DML RETURNINGに関する一般的な情報は、『Oracle Database PL/SQL言語リファレンス』RETURNING INTO句を参照してください。

ヒント:

TimesTenの準備済の文の実行後は、SQL警告を確認してください。警告イベント中には、出力パラメータは定義されません。「エラー処理」を参照してください。

この例では、TimesTenPreparedStatementインスタンスでDML RETURNINGを使用する方法を示しています。挿入された行の名前および経過時間を返します。

      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.sql.SQLWarning;
      import java.sql.Types;
      import com.timesten.jdbc.TimesTenPreparedStatement;
 
      Connection conn = null;
      ...
 
      // Insert into a table and return results
      TimesTenPreparedStatement pstmt =
        (TimesTenPreparedStatement)conn.prepareStatement
        ("insert into tab1 values(?,?) returning name, age into ?,?");
 
      // Populate table
      pstmt.setString(1,"John Doe");
      pstmt.setInt(2, 65);
 
      /* register returned parameter
       * in this case the maximum size of name is 100 chars
       */
      pstmt.registerReturnParameter(3, Types.VARCHAR, 100);
      pstmt.registerReturnParameter(4, Types.INTEGER);
 
      // process the DML returning statement
      int count = pstmt.executeUpdate();
 
      /* Check warnings; if there are warnings, values of DML RETURNING INTO
         parameters are undefined. */
      SQLWarning wn;
      boolean warningFlag = false;
      if ((wn = pstmt.getWarnings() ) != null) {
        do {
          warningFlag = true;
          System.out.println(wn);
          wn = wn.getNextWarning();
        } while(wn != null);
      }
 
      if (!warningFlag) {
        if (count>0)
        {
          ResultSet rset = pstmt.getReturnResultSet(); //rset not null, not empty
          while(rset.next())
          {
            String name = rset.getString(1);
            int age = rset.getInt(2);
            System.out.println("Name " + name + " age " + age);
          }
        }
      }

ROWIDの使用

各行には、rowidと呼ばれる行の一意の識別子があります。アプリケーションは、行のROWIDをROWID擬似列から取得できます。

ROWID値はバイナリまたは文字形式で表現され、12バイトのバイナリ形式および18バイトの文字形式で表されます。

TimesTenでは、java.sql.RowIdインタフェースとTypes.ROWID型をサポートしています。

次のResultSetメソッドを使用して、ROWIDを取得できます。

  • RowId getRowId(int columnIndex)

  • RowId getRowId(String columnLabel)

次のPreparedStatementメソッドを使用して、ROWIDを設定できます。

  • setRowId(int parameterIndex, RowId x)

アプリケーションでは、SQL文のWHERE句などで、一重引用符で囲んだCHAR定数としてリテラルのROWID値を指定できます。

使用方法やライフサイクルなど、rowidおよびROWIDデータ型に関するその他の情報は、『Oracle TimesTen In-Memory Database SQLリファレンス』ROWIDデータ型およびROWID擬似列を参照してください。

ノート:

TimesTenでは、PL/SQL型UROWIDをサポートしていません。

ラージ・オブジェクト(LOB)

TimesTen Classicでは、LOB(ラージ・オブジェクト)をサポートしています(具体的には、CLOB(Character LOB)、NCLOB(National Character LOB)およびBLOB(Binary LOB))。

この項では、LOBの概要およびLOBのJDBCでの使用について、次の内容で説明します。

次の情報も参照できます。

LOBの概要

LOBとは、ラージ・バイナリ・オブジェクト(BLOB)または文字オブジェクト(CLOBまたはNCLOB)です。TimesTenでは、BLOBは最大16 MBで、CLOBまたはNCLOBは最大4 MBになります。

記載がないかぎり、基本的にTimesTenのLOBはOracle Databaseでの場合と同様に機能します。(「TimesTenのLOBとOracle DatabaseのLOBの違い」を参照してください。)

LOBは永続する場合も一時的である場合もあります。永続LOBは、データベースのLOB列に存在します。一時LOBはアプリケーション内のみに存在します。一時LOBは、TimesTenによって黙示で作成される場合もあります。たとえば、SELECT文によって追加の文字列と連結されたLOBが選択される場合、連結データを含むようTimesTenでは一時LOBを作成します。

JDBCでのLOBオブジェクト

JDBCでは、LOBオブジェクト(BlobClobまたはNClobインスタンス)には、データ自体ではなくLOBデータへの論理ポインタがLOBオブジェクトに含まれることを意味するSQL LOBロケータ(BLOBCLOBまたはNCLOB)を使用して実装されます。

ヒント:

  • トランザクションが終了すると、TimesTenではLOBオブジェクトは無効になるので、自動コミットを有効にして使用することはできません。LOBが無効になったことを示すエラーが通知されます。

  • APIを介したLOBロケータを使用するLOB操作では、TimesTenの一時領域が使用されます。このような操作が頻繁に行われる場合には、TimesTenの一時データ領域サイズの拡大が必要になることがあります。『Oracle TimesTen In-Memory Databaseリファレンス』TempSizeを参照してください。

アプリケーションは、JDBC APIを使用して、アプリケーション内で使用するために一時LOBを明示的にインスタンス化でき、処理が終了したらLOBを解放できます。一時LOBは、TimesTenの一時データ領域に保存されます。

永続LOBを更新する場合、トランザクションで、LOBを含む行の排他ロックを取得する必要があります。これは、LOBをSELECT ... FOR UPDATE文で選択することによって実現できます。これによって、ロケータが書込み可能になります。SELECT文では、ロケータは読取り専用となります。読取り専用ロケータと書込み可能ロケータは次のように動作します。

  • 読取り専用ロケータは、存続期間中、LOBを選択したときのコンテンツのみを参照する、一貫して読み取りを行うものとなります。これには、LOBが選択される前、同じトランザクションでLOBに対して実行したすべてのコミットされていない更新が含まれることに注意してください。

  • 書込み可能ロケータは、ロケータを介した書込みのたびに、データベースの最新データで更新されます。したがって、書込みはLOBの最新データに対して行われます(これには、他のロケータを介して実行された更新も含みます)。

次に、同じLOBに対する2つの書込み可能ロケータの詳しい動作例を示します。

  1. LOB列にXYが含まれます。

  2. 更新するために、ロケータL1を選択します。

  3. 更新するために、ロケータL2を選択します。

  4. オフセット1でL1を介し、Zを書き込みます。

  5. ロケータL1を介して読み取ります。これによって、ZYが返されます。

  6. ロケータL2を介して読み取ります。L2は書込みに使用されるまで、一貫して読み取りを行うため、これによってXYが返されます。

  7. オフセット2でL2を介し、Wを書き込みます。

  8. ロケータL2を介して読み取ります。これによって、ZWが返されます。前のステップの書込みの前に、ロケータは最新のデータ(ZY)で上書きされました。

TimesTenのLOBとOracle DatabaseのLOBの違い

TimesTenでのLOBとOracle DatabaseでのLOBの重要な違いを示します。

  • TimesTenでは、LOBオブジェクトはトランザクションが終了すると無効になります。明示的か暗黙的かにかかわらず、コミットまたはロールバック後、すべてのLOBオブジェクトは無効になります。これには、あらゆる自動コミット後(自動コミットの有効化によりLOBの使用が不可能になります)、またはDDL文後が含まれます。

  • TimesTenでは、BFILE、SecureFile、LOBの配列の読取りおよび書込みまたはLOBのコールバック・ファンクションをサポートしていません。

  • TimesTenでは、LOBの連想配列のバインドはサポートしていません。

  • TimesTenでは、LOBのバッチ処理はサポートしていません。

  • BLOBに関して、TimesTenの16進リテラルの使用法に違いがあります。『Oracle TimesTen In-Memory Database SQLリファレンス』定数HexadecimalLiteralの説明を参照してください。

LOBファクトリ・メソッド

TimesTenでは、標準のConnectionメソッドのcreateBlob()createClob()およびcreateNClob()をサポートしています。

Oracle TimesTen In-Memory Database JDBC拡張機能Java APIリファレンスを参照してください。

ヒント:

TimesTenでは、LOBオブジェクトを作成すると、まだ進行中でない場合は、データベース・トランザクションが作成されます。コミットまたはロールバックを実行し、トランザクションをクローズする必要があります。

LOBのgetterメソッドとsetterメソッド

LOBには、他のデータ型の場合と同様に、標準のjava.sql.ResultSetPreparedStatementおよびCallableStatementインタフェースで定義するgetterメソッドおよびsetterメソッドを介してアクセスできます。

適切なgetXXX()メソッドを使用してLOBの結果または出力パラメータを取得するか、setXXX()メソッドを使用てしLOB入力パラメータをバインドします。

  • ResultSet getterメソッド: 列名または列索引のいずれかに基づいてLOBに取得を指定する、getBlob()メソッド、getClob()メソッドおよびgetNClob()メソッドがあります。

    BlobClobまたはNClobオブジェクトを取得するgetObject()も使用できます。

  • PreparedStatement setterメソッド: BlobClobまたはNClobインスタンスとパラメータ索引を入力し、入力パラメータをバインドする、setBlob()メソッド、setClob()メソッドおよびsetNClob()メソッドがあります。

    BlobClobまたはNClob入力パラメータをバインドするsetObject()も使用できます。

    また、Blobインスタンスのかわりに、InputStreamインスタンスまたはInputStreamインスタンスと長さを指定するsetBlob()メソッドもあります。

    setClob()およびsetNClob()メソッドでは、ClobまたはNClobインスタンスのかわりに、ReaderインスタンスまたはReaderインスタンスと長さを指定します。

  • CallableStatement getterメソッド: パラメータ名またはパラメータ索引のいずれかに基づいてLOB出力パラメータを取得するgetBlob()メソッド、getClob()メソッドおよびgetNClob()メソッドがあります。

    BlobClobまたはNClob出力パラメータを取得するgetObject()も使用できます。

    また、CallableStatementオブジェクトから出力パラメータを登録する必要もあります。registerOutParameter()メソッドでは、パラメータ索引とともにTypes.BLOBTypes.CLOBまたはTypes.NCLOBのSQL型を取ります。

  • CallableStatement setterメソッド: これは、PreparedStatement setterメソッドと同一です(継承されます)。

Oracle TimesTen In-Memory Database JDBC拡張機能Java APIリファレンスを参照してください。

TimesTenのLOBインタフェース・メソッド

Blobインスタンスをcom.timesten.jdbc.TimesTenBlobに、Clobインスタンスをcom.timesten.jdbc.TimesTenClobに、NClobインスタンスをcom.timesten.jdbc.TimesTenNClobにキャストできます。

これらのインタフェースでは、java.sql.BlobClobおよびNClobインタフェースで指定するメソッドをサポートしています。

Blobの機能の概要は、次のとおりです。

  • TimesTenの拡張であるisPassthrough()メソッドは、BLOBがOracle DatabaseからのパススルーLOBであるかどうかを示します。

  • アプリケーションが処理を完了したら、Blobリソースを解放します。

  • BLOB値をバイナリ・ストリームとして取得します。一部または全部を取得するメソッドがあります。

  • バイト配列として、BLOB値の全部または一部を取得します。

  • BLOBのバイト数を戻します。

  • BLOBへのバイナリ・データの書込み(指定した位置から開始)に使用するストリームを取得します。これは既存のデータを上書きします。

  • BLOBに書き込むバイトの配列を指定し(指定した位置から開始)、書き込んだバイト数を戻します。これは既存のデータを上書きします。配列の全部または一部を書き込むメソッドがあります。

  • 指定した長さにBLOBを切り捨てます。

ClobおよびNClobの機能の概要は、次のとおりです。

  • TimesTenの拡張であるisPassthrough()メソッドは、CLOBまたはNCLOBがOracle DatabaseからのパススルーLOBであるかどうかを示します。

  • アプリケーションが処理を終了したら、ClobまたはNClobリソースを解放します。

  • CLOBまたはNCLOBをASCIIストリームとして取得します。

  • CLOBまたはNCLOBをjava.io.Readerオブジェクト(または文字のストリーム)として取得します。一部または全部を取得するメソッドがあります。

  • CLOBまたはNCLOB内の指定したサブストリングのコピーを、指定の最大長まで(指定した位置から開始して)取得します。

  • CLOBまたはNCLOBの文字数を戻します。

  • CLOBまたはNCLOBへのASCII文字の書込み(指定した位置から開始)に使用するストリームを取得します。これは既存のデータを上書きします。

  • CLOBまたはNCLOBに書き込む(指定した位置から開始)、Java String値を指定します。これは既存のデータを上書きします。String値の全部または一部を書き込むメソッドがあります。

  • 指定した長さにCLOBまたはNCLOBを切り捨てます。

ノート:

  • LOBにデータを書き込むメソッドの場合、書き込まれるデータよりも少ない領域しか指定した位置以降にLOBにない場合を除き、LOBのサイズは変わりません。その場合、データが収まるようLOBのサイズが拡張されます。

  • LOBの書込みを指定した位置の値が、LOBの長さに1を足したものより大きい場合の動作は定義されていません。

Oracle TimesTen In-Memory Database JDBC拡張機能Java APIリファレンスを参照してください。

LOBのプリフェッチ

クライアント/サーバー接続でのサーバーへのラウンドトリップを減らすために、データベースからLOBをフェッチするとき、デフォルトでLOBのプリフェッチが有効になっています。プリフェッチのデフォルト・サイズは、BLOBの場合は4,000バイトで、CLOBまたはNCLOBの場合は4,000文字です。

TimesTenConnectionプロパティCONNECTION_PROPERTY_DEFAULT_LOB_PREFETCH_SIZEを使用すると、デフォルト値とは異なる値を接続のすべての文に適用するよう設定できます。値-1を使用すると、その接続ではデフォルトでLOBのプリフェッチが無効になり、0(ゼロ)を使用するとデフォルトでメタデータのみのLOBのプリフェッチが有効になり、0より大きい任意の値を指定すると、フェッチ操作時にLOBロケータとともに、デフォルトでBLOBのバイト数またはCLOBとNCLOBの文字数がプリフェッチされるよう指定できます。

文レベルで次のTimesTenStatementメソッドを使用すると、接続のプリフェッチ・サイズの操作とデフォルト値の上書きが可能になります。

  • setLobPrefetchSize(int): 文の新しいLOBプリフェッチ値を指定します。

  • int getLobPrefetchSize(): 文に適用されている現在のLOBプリフェッチ値を戻します(該当する文自体に設定した値または接続のデフォルト値)。

Oracle TimesTen In-Memory Database JDBC拡張機能Java APIリファレンスを参照してください。

パススルーLOB

パススルーLOB (TimesTenを介してアクセスする、Oracle Database内のLOB)は、TimesTenのLOBとして公開され、TimesTenのLOBとほぼ同様にTimesTenでサポートされています。

次の点に注意してください:

  • 「TimesTenのLOBインタフェース・メソッド」で示したとおり、TimesTenBlobTimesTenClobおよびTimesTenNClobインタフェースでは、そのLOBがパススルーLOBであるかどうかを示す次のメソッドを指定します:

    boolean isPassthrough()

  • TimesTenのLOBのサイズ制限は、パススルーによるOracle DatabaseのLOBの保存には適用されません。

  • TimesTenのローカルのLOBと同様に、パススルーLOBオブジェクトはトランザクションが終了すると無効になります。

Oracle TimesTen In-Memory Database JDBC拡張機能Java APIリファレンスを参照してください。

プロシージャおよびファンクションを実行するためのCALLの使用

TimesTenでサポートされている、PL/SQLプロシージャ(procname)またはPL/SQLファンクション(funcname) (これらはスタンドアロンの場合とパッケージの一部である場合がある)、あるいはTimesTen組込みプロシージャ(procname)をコールするためのそのプログラミング・インタフェースの各構文書式を次に示します。

CALL procname[(argumentlist)]

CALL funcname[(argumentlist)] INTO :returnparam

CALL funcname[(argumentlist)] INTO ?

TimesTenのJDBCでは、次の構文の書式もサポートしています。

{ CALL procname[(argumentlist)] }

{ ? = [CALL] funcname[(argumentlist)] }

{ :returnparam = [CALL] funcname[(argumentlist)] }

プロシージャおよびファンクションは、(結果セットをいつ返すかなどの)準備ステップがある場合はそれを先にして、CallableStatementインタフェースを介して実行します。

次の例では、TimesTen組込みプロシージャのttCkptをコールしています(より完全なJDBC構文の例については、この項の後半にあるttCkptの例も参照してください。)

CallableStatement.execute("call ttCkpt")

次の例では、TimesTen組込みプロシージャのttDataStoreStatusをコールしています。このプロシージャでは結果セットが生成されるため、準備コールが使用されています。(より完全なJDBC構文の例については、この項の後半にあるttDataStoreStatusの例も参照してください。)

CallableStatement cStmt = null;
cStmt = conn.prepareCall("call ttDataStoreStatus");
cStmt.execute();

次の例では、2つのパラメータを使用し、PL/SQLプロシージャmyprocをコールしています。

cStmt.execute("{ call myproc(:param1, :param2) }");

cStmt.execute("{ call myproc(?, ?) }");

次にPL/SQLファンクションmyfuncをコールするいくつかの方法を示します。

cStmt.execute("CALL myfunc() INTO :retparam");

cStmt.execute("CALL myfunc() INTO ?");

cStmt.execute("{ :retparam = myfunc() }");

cStmt.execute("{ ? = myfunc() }");

『Oracle TimesTen In-Memory Database SQLリファレンス』CALLを参照してください。

ノート:

ユーザー独自のプロシージャは、同じ名前を持ったTimesTen組込みプロシージャより優先されますが、このような命名の競合は回避することが最適です。

この例では、ttCkptプロシージャをコールしてファジー・チェックポイントを開始します。

Connection conn = null;
CallableStatement cStmt = null;
.......
cStmt = conn.prepareCall("{ Call ttCkpt }");
cStmt.execute();
conn.commit();           // commit the transaction

ttCkpt組込みプロシージャには、ADMIN権限が必要なことに注意してください。『Oracle TimesTen In-Memory Databaseリファレンス』ttCkptを参照してください。

次の例では、ttDataStoreStatusプロシージャをコールして、返される結果セットを出力します。結果セットを返す組込みプロシージャについては、ResultSetインタフェースのgetXXX()メソッドを使用して、次のようにデータを取得できます。

「TimesTen結果セットの使用: ヒントおよび制限」に示した例とは異なり、この例では、ResultSetオブジェクトでgetString()コールを使用して、バイナリであるContextフィールドを取得します。これは、出力は処理で使用されるのではなく、表示されるためです。Context値を表示しない場合は、getBytes()メソッドをかわりに使用すると、より高いパフォーマンスが得られます。

ResultSet rs;

CallableStatement cStmt = conn.prepareCall("{ Call ttDataStoreStatus }");

if (cStmt.execute() == true) {
    rs = cStmt.getResultSet();
    System.out.println("Fetching result set...");
    while (rs.next()) {
      System.out.println("\n Database: " + rs.getString(1));
      System.out.println(" PID: " + rs.getInt(2));
      System.out.println(" Context: " + rs.getString(3));
      System.out.println(" ConType: " + rs.getString(4));
      System.out.println(" memoryID: " + rs.getString(5));
      }
    rs.close();
  }
cStmt.close();

SQL文の実行に対するタイムアウトまたはしきい値の設定

TimesTenには、SQL文の実行時間を制限する2通りの方法があり、execute()executeBatch()executeQuery()executeUpdate()またはnext()のコールで使用できます。1つの方法はタイムアウトを設定する方法で、もう1つの方法はしきい値を設定する方法です。

このメカニズムについては、次の項で説明します。

SQL文のタイムアウト期間の設定

TimesTenでは、タイムアウト期間に達すると、文が実行を停止し、エラーがスローされるSQLタイムアウトを指定できます。

SQLQueryTimeout一般接続属性(秒)またはSQLQueryTimeoutMsec一般接続属性(ミリ秒)を使用することで、タイムアウト値を接続、つまり接続の任意の文に対して指定できます。それぞれのデフォルト値は0で、タイムアウトはありません。(『Oracle TimesTen In-Memory Databaseリファレンス』SQLQueryTimeoutSQLQueryTimeoutMsecも参照してください。)

名前に反して、これらのタイムアウト値は問合せだけでなく、実行可能な任意のSQL文に適用されます。

特定の文について、StatementメソッドsetQueryTimeout()をコールすることで、SQLQueryTimeout設定を上書きすることができます。

問合せのタイムアウト制限は、SQL文がアクティブに実行されている場合のみ有効です。処理のコミット中またはロールバック中にタイムアウトは発生しません。多数の行を更新、挿入、削除するトランザクションでは、コミットまたはロールバックの行程が完了するまでに時間がかかる場合があります。その間、タイムアウト値は無視されます。

その他のタイムアウト設定でのSQL問合せタイムアウトの考慮事項については、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』SQLおよびPL/SQLのタイムアウト値の選択を参照してください。

ノート:

ロック・タイムアウト値およびSQL問合せタイムアウト値の両方が指定されている場合は、まず、2つの値の小さい方の値によってタイムアウトが発生します。ロック・タイムアウトについては、『Oracle TimesTen In-Memory Databaseリファレンス』ttLockWait(組込みプロシージャ)またはLockWait(一般接続属性)、あるいは『Oracle TimesTen In-Memory Databaseモニタリングおよびトラブルシューティング・ガイド』デッドロックとタイムアウトの確認を参照してください。

SQL文のしきい値期間の設定

TimesTenでは、SQLしきい値期間(秒単位)を設定できます。しきい値に達すると、サポート・ログに警告が書き込まれますが、実行は続行されます。

名前に反して、このしきい値は問合せだけでなく、SQL文を実行する任意のJDBCコールに適用されます。

デフォルトでは、アプリケーションはしきい値をQueryThreshold一般接続属性設定から取得します。デフォルトは0 (警告なし)です。データベースの接続URLにQueryThreshold属性を含めることでJDBC Connectionオブジェクトのしきい値を上書きすることができます。たとえば、QueryThresholdの値をmyDSNデータベース用に5秒に設定するには、次のようにします。

jdbc:timesten:direct:dsn=myDSN;QueryThreshold=5

TimesTenStatementオブジェクトのsetQueryTimeThreshold()メソッドを使用して、しきい値を設定することもできます。これは、接続属性設定およびConnection オブジェクト設定を上書きします。

TimesTenStatementオブジェクトのgetQueryTimeThreshold()メソッドを使用して現行のしきい値を取得できます。

Oracle TimesTen In-Memory Database JDBC拡張機能Java APIリファレンスを参照してください。

JDBCを使用したクライアント/サーバーでの結果セット・バッファ・サイズの構成

クライアント/サーバーでSELECT文から返されるデータについては、クライアントに返されるデータのバッファ・サイズは構成可能であり、パフォーマンス向上のために調整できます。(以前のリリースでは、バッファ・サイズを変更できませんでした。)

バッファ・サイズは、データ行またはデータのバイトのいずれかについて設定できます。下限が優先されます。

クライアント/サーバーの場合、StatementおよびResultSetオブジェクトのsetFetchSize()およびgetFetchSize()メソッドのTimesTen実装では、データの最大行数を設定または取得できます。

  • void setFetchSize(int rows)
  • int getFetchSize()

移植性のために、これはバッファ・サイズを設定するための推奨方法です。デフォルト値は8192です。この値を大きな値に設定すると、次に示すように、最大バイト数を設定して制約にならないようにする必要があります。

また、次のメソッドはTimesTenStatementにあります。

  • void setTtNetMsgMaxRows(int rows)
  • int getTtNetMsgMaxRows()
  • void setTtNetMsgMaxBytes(int bytes)
  • int getTtNetMsgMaxBytes()

また、setメソッドはTimesTenConnectionにもあります。

  • void setTtNetMsgMaxRows(int rows)
  • void setTtNetMsgMaxBytes(int bytes)

デフォルトの行数は8192で、デフォルトのバイト数は2097152または2MBです。一方の制限を使用し、もう一方の制限を、先に到達しないように十分大きい値に設定することをお薦めします。

接続オブジェクトに対してTimesTenのsetterメソッドのいずれかを使用すると、その値は、接続で作成された将来の文オブジェクト、および接続上の既存の文オブジェクトにも適用されます。ただし、文レベルで(または、作成する文ハンドルの初期値として機能する接続レベルでのみ)設定する際に、お薦めします。

ノート:

  • これらの設定は、TimesTen接続属性TT_NetMsgMaxRowsおよびTT_NetMsgMaxBytesに対応しており、TimesTen接続文字列またはDSNで設定して、接続で作成されるすべての文の初期値として使用できます。
  • 各設定の最小値は1で、少なくとも1つの行が常に返されます。行またはバイトのいずれかの値を0に設定すると、その設定にデフォルト値が使用されます。データ型の最大値(32ビット符号付き整数)以外の最大設定はありません。
  • これらの属性をサポートするクライアント・バージョンが、サポートしないサーバー・バージョンに接続すると、設定は暗黙的に無視されます。

キャッシュで使用する機能

この項では、キャッシュ操作の使用に関連する機能を説明します。

Oracle Databaseパスワードの設定

OraclePassword属性は、Oracle Databaseパスワードにマップされます。TimesTenDataSourceメソッドsetOraclePassword()を使用してOracle Databaseのパスワードを設定できます。

例については、「データベースへの接続」を参照してください。

ttOptSetFlag組込みプロシージャでの一時パススルー・レベルの設定

TimesTenでは、パススルー・レベルを一時的に設定するPassThroughフラグを含め、様々なフラグの設定にttOptSetFlag組込みプロシージャを用意しています。

ttOptSetFlagを使用すると、次のサンプル文のようにJDBCアプリケーションでPassThroughを設定できます(この場合、パススルー・レベルは1に設定されます)。この設定は、トランザクションの最後までの準備されているすべての文に影響します。

pstmt = conn.prepareStatement("call ttoptsetflag('PassThrough', 1)");

次の例には、これらのステップを実行するサンプル・コードがあります。

  1. パススルー・レベル用に、バインド・パラメータを使用するttOptSetFlagをコールする準備済文(PreparedStatementインスタンスthePassThroughStatement)を作成します。

  2. 指定したパススルー設定を取るメソッドsetPassthrough()を定義し、これを準備済文にバインドし、準備済文を実行して、パススルー・レベルを設定するttOptSetFlagをコールします。

  thePassThroughStatement = 
         theConnection.prepareStatement("call ttoptsetflag('PassThrough', ?)");
  ...
  private void setPassthrough(int level) throws SQLException{
    thePassThroughStatement.setInt(1, level);
    thePassThroughStatement.execute();
  }

『Oracle TimesTen In-Memory Databaseリファレンス』ttOptSetFlagおよびPassThroughを参照してください。パススルー設定については、『Oracle TimesTen In-Memory Databaseキャッシュ・ガイド』パススルー・レベルの設定を参照してください。

パススルー・ステータスの確認

TimesTenPreparedStatementのメソッドgetPassThroughType()をコールすると、SQL文がTimesTenデータベースで実行されるか実行のためにOracleデータベースにパススルーされるかを特定できます。

PassThroughType getPassThroughType()

戻り値の型であるTimesTenPreparedStatement.PassThroughTypeは、TimesTen PassThrough接続属性の値の列挙型です。

SQL文の準備の後に、このコールを実行できます。これは、PassThrough設定1または2の場合(文が実際にパススルーされるかどうかの確認がコンパイル時まで行われない)に有効です。

『Oracle TimesTen In-Memory Databaseキャッシュ・ガイド』パススルー・レベルの設定を参照してください。

キャッシュ・グループの管理

TimesTenで、FLUSH CACHE GROUPLOAD CACHE GROUPREFRESH CACHE GROUPまたはUNLOAD CACHE GROUP文を実行すると、StatementメソッドgetUpdateCount()によって、フラッシュ、ロード、リフレッシュ、アンロードされたキャッシュ・インスタンスの数が返されます。

『Oracle TimesTen In-Memory Databaseキャッシュ・ガイド』操作の影響を受けるキャッシュ・インスタンスの数の確認を参照してください。

レプリケーションで使用する機能

レプリケーションを使用するTimesTen Classicアプリケーションの場合、パラレル・レプリケーションを使用することでパフォーマンスを向上させることができます。パラレル・レプリケーションでは、並行して動作する複数のスレッドを使用して、レプリケーション・スキーム内のデータベースにトランザクションの変更をレプリケートおよび適用します。

TimesTenでは、次のタイプのパラレル・レプリケーションをサポートしています。

  • 自動パラレル・レプリケーション(ReplicationApplyOrdering=0): トランザクションの依存性と、コミット順に適用されたすべての変更を自動的に強制する、複数のスレッドにおけるパラレル・レプリケーション。これはデフォルトです。

  • コミット依存性を無効にした自動パラレル・レプリケーション(ReplicationApplyOrdering=2): トランザクションの依存性を自動的に強制するが、サブスクライバ・データベース上でマスター・データベース上と同じ順序でコミットされるトランザクションは強制しない、複数スレッドでのパラレル・レプリケーション。このモードでは、オプションでレプリケーション・トラックを指定できます。

『Oracle TimesTen In-Memory Databaseレプリケーション・ガイド』パラレル・レプリケーションの構成を参照してください。

パラレル・レプリケーションを使用し、レプリケーション・トラックを指定するJDBCアプリケーションの場合は、後述のTimesTenConnectionメソッドを通じて、接続でトラック番号を指定できます。(または、一般接続属性のReplicationTrackまたはALTER SESSIONパラメータREPLICATION_TRACKを使用します)。

  • void setReplicationTrack(int track)

TimesTenConnectionにも、対応するgetterメソッドがあります。

  • int getReplicationTrack()

Oracle TimesTen In-Memory Database JDBC拡張機能Java APIリファレンスを参照してください。