6 JDBCアプリケーションのSQL翻訳のAPIリファレンス
oracle.jdbcパッケージの一部であるAPI、特に、SQL翻訳の一翼を担うoracle.jdbcの要素について詳しく見ていきます。JDBCアプリケーションを正常に移行するには、翻訳のプロパティやインタフェース、エラーの翻訳メカニズムを理解することが重要です。
関連項目:
-
Oracle Database JDBC Java APIリファレンスの
oracle.jdbcパッケージのドキュメント一式
6.1 翻訳プロパティ
翻訳プロパティを表6-1に示します
表6-1 翻訳プロパティ
| プロパティ | 説明 |
|---|---|
|
翻訳プロファイルの名前を指定します。 |
|
|
SQLエラー翻訳ファイルのパスを指定します。 |
6.1.1 sqlTranslationProfile
プロパティoracle.jdbc.sqlTranslationProfileは、翻訳プロファイルの名前を指定します。
宣言
oracle.jdbc.sqlTranslationProfile
定数
OracleConnection.CONNECTION_PROPERTY_SQL_TRANSLATON_PROFILE
定数の値は、oracle.jdbc.sqlTranslationProfileです。これは、プロパティ名でもあります。
プロパティの値
値は文字列です。デフォルト値はありません。
注釈
プロパティsqlTranslationProfileは、システム・プロパティまたは接続プロパティのいずれかとして設定できます。SQL翻訳を使用するには、このプロパティが必要です。このプロパティを設定する場合、その他で特に指定しないかぎり、接続で作成されるすべての文でSQL翻訳が有効になります。
6.1.2 sqlErrorTranslationFile
プロパティoracle.jdbc.sqlErrorTranslationFileは、SQLエラー翻訳ファイルのパスを指定します。
宣言
oracle.jdbc.sqlErrorTranslationFile
定数
Oracle.connection.CONNECTION_PROPERTY_SQL_ERROR_TRANSLATION_FILE.
プロパティ値
値はパス名です。デフォルト値はありません。
例外
接続を確立する際のエラーによって、SQLExceptionが生じますが、有効な接続はありません。ただし、SQLエラー翻訳ファイルのパスは、システム・プロパティまたは接続プロパティのいずれかとして利用でき、エラーの翻訳に使用されます。
備考
このファイルは、接続の確立が失敗したときに生じるエラーの翻訳にのみ使用されます。接続が確立すると、このファイルは無視され、接続の確立後に生じるエラーの翻訳の詳細が含まれる場合でも考慮されません。プロパティsqlErrorTranslationFileは、システム・プロパティまたは接続プロパティのいずれかとして設定できます。このファイルのコンテンツは、有効な接続がない場合に、Oracle SQLExceptionsを外部SQLExceptionsに翻訳する際に使用されます。
6.2 OracleTranslatingConnectionインタフェース
このインタフェースは、SQL翻訳をサポートするConnectionオブジェクトによってのみ実装されます。このインタフェースの主な目的は、翻訳接続から非翻訳文(preparedStatementおよびCallableStatementを含む)を取得することです。
publicインタフェースoracle.jdbc.OracleTranslatingConnectionは、翻訳および非翻訳Statementオブジェクトを作成するためのファクトリ・メソッドを定義します。
OracleTranslatingConnectionの列挙を表6-2に示します。
表6-2 OracleTranslatingConnectionの列挙
| 名前 | 説明 |
|---|---|
|
マップのキーを提供します。 |
OracleTranslatingConnectionメソッドを表6-3に示します。
表6-3 OracleTranslatingConnectionメソッド
| 名前 | 説明 |
|---|---|
|
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
|
|
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
|
|
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
|
|
SQL翻訳時に問合せのすべての翻訳バージョンのマップを戻します。 |
6.2.1 SqlTranslationVersion
SqlTranslationVersion列挙値は、getSQLTranslationVersions()メソッドのキーを指定します。
構文
public enum SqlTranslationVersion {
ORIGINAL_SQL,
JDBC_MARKER_CONVERTED,
TRANSLATED
}
次の表では、SqlTranslationVersionのすべての列挙値と、それぞれの列挙値の説明を示します。
| メンバー名 | 説明 |
|---|---|
|
|
元のベンダーに固有のSQLを指定します。 |
JDBC_MARKER_CONVERTED |
JDBCパラメータ・マーカー('?')がOracleスタイルのパラメータ・マーカー(':b<n>')で置き換えられるように指定します。このため、連続する'?'は、 |
TRANSLATED |
サーバーから戻される翻訳済問合せを指定します。 |
6.2.2 createStatement()
このグループのメソッドは、Statementオブジェクトを作成し、文がSQL翻訳をサポートするかどうかを指定します。パラメータtranslatingの値がTRUEの場合、返される文は翻訳をサポートし、translating引数を指定しないjava.sql.Connectionインタフェースの対応するバージョンと同一です。値がFALSEの場合、戻り文は翻訳をサポートしません。
| 構文 | 説明 |
|---|---|
public Statement createStatement( boolean translating) throws SQLException; |
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
public Statement createStatement( int resultSetType, int resultSetConcurrency, boolean translating) throws SQLException; |
SQLを翻訳するオプションまたは翻訳しないオプションを指定して、指定のタイプと同時性で |
public Statement createStatement( int resultSetType, int resultSetConcurrency, int resultSetHoldability, boolean translating) throws SQLException; |
SQLを翻訳するオプションまたは翻訳しないオプションを指定して、指定のタイプ、同時性および持続性で |
パラメータ
| パラメータ | 説明 |
|---|---|
resultSetType |
結果セットのタイプを表す |
resultSetConcurrency |
結果セットの同時性タイプを表す |
|
|
結果セットの持続性タイプを表す |
translating |
文が翻訳をサポートするかどうかを指定します。 |
戻り値
createStatement()メソッドは、Statementオブジェクトを戻します。
例外
createStatement()メソッドは、SQLExceptionをスローします。
例
例を実行する前に次のパッケージをインポートします。
import java.sql.*; import java.util.Properties; import oracle.jdbc.OracleConnection; import oracle.jdbc.OracleTranslatingConnection; import oracle.jdbc.pool.OracleDataSource;
次のSQL文を実行します。
conn system/manager; grant create sql translation profile to HR; conn username/pwd; drop table sample_tab; create table sample_tab (c1 number, c2 varchar2(100)); insert into sample_tab values (1, 'A'); insert into sample_tab values (2, 'B'); commit; exec dbms_sql_translator.drop_profile('FOO'); exec dbms_sql_translator.create_profile('FOO'); exec dbms_sql_translator.register_sql_translation('FOO','select row of (c1, c2) from sample_tab','select c1, c2 from sample_tab');
例6-1 createStatement()メソッドの使用
public class SQLTransStmt
{
static String url="jdbc:oracle:thin:@localhost:5521:orcl";
static String user="username", pwd="pwd";
static String PROFILE = "FOO";
static String primitiveSql = "select row of (c1, c2) from sample_tab";
public static void main(String[] args) throws Exception
{
OracleDataSource ods = new OracleDataSource();
ods.setURL(url);
Properties props = new Properties();
props.put("user", user);
props.put("password", pwd);
props.put(OracleConnection.CONNECTION_PROPERTY_SQL_TRANSLATION_PROFILE, PROFILE);
ods.setConnectionProperties(props);
Connection conn = ods.getConnection();
System.out.println("connection for SQL translation: "+conn);
try{
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println("Call: oracle.jdbc.OracleTranslatingConnection.createStatement(true)");
Statement trStmt = trConn.createStatement(true);
System.out.println("executeQuery for: "+primitiveSql);
ResultSet trRs = trStmt.executeQuery(primitiveSql);
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.close();
trStmt.close();
}catch (Exception e) {
e.printStackTrace();
}
try{
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println("Call: oracle.jdbc.OracleTranslatingConnection.createStatement(false)");
Statement trStmt = trConn.createStatement(false);
System.out.println("executeQuery for: "+primitiveSql);
ResultSet trRs = trStmt.executeQuery(primitiveSql);
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.close();
trStmt.close();
}catch (Exception e) {
System.out.println("expected Exception: "+e.getMessage());
}
try{
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println("Call: oracle.jdbc.OracleTranslatingConnection.
createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, true)");
Statement trStmt = trConn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, true);
System.out.println("executeQuery for: "+primitiveSql);
ResultSet trRs = trStmt.executeQuery(primitiveSql);
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
System.out.println("move resultset back to 2nd row...");
trRs.absolute(2);
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.close();
trStmt.close();
}catch (Exception e) {
e.printStackTrace();
}
try{
conn.setAutoCommit(false);
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println("Call: oracle.jdbc.OracleTranslatingConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE,
ResultSet.HOLD_CURSORS_OVER_COMMIT, true)");
Statement trStmt = trConn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT, true);
System.out.println("executeQuery for: "+primitiveSql);
ResultSet trRs = trStmt.executeQuery(primitiveSql);
trRs.last();
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.updateString(2, "Hello");
trRs.updateRow();
conn.commit();
System.out.println("accept the update and list all of the rows again...");
trRs.beforeFirst();
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.close();
trStmt.close();
}catch (Exception e) {
e.printStackTrace();
}
conn.close();
}
}
6.2.3 prepareCall()
このグループのメソッドは、CallableStatementオブジェクトを作成し、文がSQL翻訳をサポートするかどうかを指定します。パラメータtranslatingの値がTRUEの場合、戻り文は翻訳をサポートしません。値がFALSEの場合、戻り文は翻訳をサポートしません。
| 構文 | 説明 |
|---|---|
public CallableStatement prepareCall( String sql, boolean translating) throws SQLException; |
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
public CallableStatement prepareCall( String sql, int resultSetType, int resultSetConcurrency, boolean translating) throws SQLException; |
SQLを翻訳するオプションまたは翻訳しないオプションを指定して、指定のタイプと同時性で |
public CallableStatement prepareCall( String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability, boolean translating) throws SQLException; |
SQLを翻訳するオプションまたは翻訳しないオプションを指定して、指定のタイプ、同時性および持続性で |
パラメータ
| パラメータ | 説明 |
|---|---|
|
|
データベースに送信される |
resultSetType |
結果セットのタイプを表す |
resultSetConcurrency |
結果セットの同時性タイプを表す |
|
|
結果セットの持続性タイプを表す |
translating |
文が翻訳をサポートするかどうかを指定します。 |
戻り値
prepareCall()メソッドはCallableStatementオブジェクトを戻します。
例外
prepareCall()メソッドは、SQLExceptionをスローします。
例
例を実行する前に次のパッケージをインポートします。
import java.sql.*; import java.util.Properties; import oracle.jdbc.OracleConnection; import oracle.jdbc.OracleTranslatingConnection; import oracle.jdbc.pool.OracleDataSource;
次のSQL文を実行します。
conn system/manager; grant create sql translation profile to HR; conn username/pwd; create or replace procedure sample_proc (p_num number, p_vchar in out varchar2) AS begin p_vchar := 'p_num'||p_num||', p_vchar'||p_vchar; end; / exec dbms_sql_translator.drop_profile('FOO'); exec dbms_sql_translator.create_profile('FOO'); exec dbms_sql_translator.register_sql_translation('FOO', 'exec sample_proc(:b1, :b2)', '{call sample_proc(:b1, :b2)}');
例6-2 prepareCall()メソッドの使用
public class SQLTransCstmt
{
static String url="jdbc:oracle:thin:@localhost:5521:orcl";
static String user="username", pwd="pwd";
static String PROFILE = "FOO";
static String primitiveSql = "exec sample_proc(:b1, :b2)";
public static void main(String[] args) throws Exception
{
OracleDataSource ods = new OracleDataSource();
ods.setURL(url);
Properties props = new Properties();
props.put("user", user);
props.put("password", pwd);
props.put(OracleConnection.CONNECTION_PROPERTY_SQL_TRANSLATION_PROFILE,
PROFILE);
ods.setConnectionProperties(props);
Connection conn = ods.getConnection();
System.out.println("connection for SQL translation: "+conn);
try{
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println(
"Call: oracle.jdbc.OracleTranslatingConnection.prepareCall(sql, true)");
CallableStatement trStmt = trConn.prepareCall(primitiveSql, true);
trStmt.setInt("b1", 1);
trStmt.setString("b2", "A");
trStmt.registerOutParameter("b2", Types.VARCHAR);
System.out.println("execute for: "+primitiveSql);
trStmt.execute();
System.out.println("out param: "+trStmt.getString("b2"));
trStmt.close();
}catch (Exception e) {
e.printStackTrace();
}
try{
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println(
"Call: oracle.jdbc.OracleTranslatingConnection.prepareCall(sql, false)");
CallableStatement trStmt = trConn.prepareCall(primitiveSql, false);
trStmt.setInt(1, 1);
trStmt.setString(2, "A");
System.out.println("execute for: "+primitiveSql);
ResultSet trRs = trStmt.executeQuery();
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.close();
trStmt.close();
}catch (Exception e) {
System.out.println("expected Exception: "+e.getMessage());
}
conn.close();
}
}6.2.4 prepareStatement()
このグループのメソッドは、PreparedStatementオブジェクトを作成し、文がSQL翻訳をサポートするかどうかを指定します。パラメータtranslatingの値がTRUEの場合、戻り文は翻訳をサポートしません。値がFALSEの場合、戻り文は翻訳をサポートしません。
| 構文 | 説明 |
|---|---|
public PreparedStatement prepareStatement( String sql, boolean translating) throws SQLException; |
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
public PreparedStatement prepareStatement( String sql, int resultSetType, int resultSetConcur, boolean translating) throws SQLException; |
SQLを翻訳するオプションまたは翻訳しないオプションを指定して、指定のタイプと同時性で |
public PreparedStatement prepareStatement(
String sql,
int resultSetType,
int resultSetConcur,
int resultSetHold,
boolean translating)
throws SQLException;
|
SQLを翻訳するオプションまたは翻訳しないオプションを指定して、指定のタイプ、同時性および持続性で |
| パラメータ | 説明 |
|---|---|
|
|
データベースに送信される |
resultSetType |
結果セットのタイプを表す |
resultSetConcur |
結果セットの同時性タイプを表す |
|
|
結果セットの持続性タイプを表す |
translating |
文が翻訳をサポートするかどうかを指定します。 |
戻り値
prepareStatement()メソッドはPreparedStatementオブジェクトを戻します。
使用上のノート
"?"プレースホルダをprepareStatement()メソッドで使用する場合、サーバー側トランスレータで操作できるのはOracleスタイルのマーカーのみであるため、ドライバは内部で"?"をOracleスタイルのパラメータに変更します。これは、バインド変数の区別に必要です。これを行わない場合、バインド変数の順序の変更が区別されません。置き換えられたOracleスタイルのマーカーは、形式:b<n>に従い、<n>は増分番号です。たとえば、exec sample_proc(?,?)はexec sample_proc(:b1,:b2)になります。
さらに実証するために、上位3行を選択するベンダー問合せがSELECT * FROM employees WHERE first_name=? AND employee_id=? TOP 3である、ベンダー形式のシナリオについて考えます。問合せはOracle言語に変換する必要があります。この場合、次の翻訳がサーバーに登録されます。
翻訳前:
SELECT * FROM employees WHERE first_name=:b1 AND employee_id=:b2 TOP 3
翻訳後:
SELECT * FROM employees WHERE first_name=:b1 AND employee_id=:b2 AND ROWNUM <= 3
詳細は、「SqlTranslationVersion」および「JDBCアプリケーションのSQL翻訳」を参照してください。
例外
prepareStatement()メソッドは、SQLExceptionをスローします。
例
例を実行する前に次のパッケージをインポートします。
import java.sql.*; import java.util.Properties; import oracle.jdbc.OracleConnection; import oracle.jdbc.OracleTranslatingConnection; import oracle.jdbc.pool.OracleDataSource;
次のSQL文を実行します。
conn system/manager; grant create sql translation profile to USER; conn username/pwd; drop table sample_tab; create table sample_tab (c1 number, c2 varchar2(100)); insert into sample_tab values (1, 'A'); insert into sample_tab values (1, 'A'); insert into sample_tab values (1, 'A'); commit; exec dbms_sql_translator.drop_profile('FOO'); exec dbms_sql_translator.create_profile('FOO'); exec dbms_sql_translator.register_sql_translation('FOO','select row of select c1, c2 from sample_tab where c1=:b1 and c2=:b2','select c1, c2 from sample_tab where c1=:b1 and c2=:b2');
例6-3 prepareStatement()メソッドの使用
public class SQLTransPstmt
{
static String url="jdbc:oracle:thin:@localhost:5521:orcl";
static String user="username", pwd="pwd";
static String PROFILE = "FOO";
static String primitiveSql = "select row of select c1, c2 from sample_tab
where c1=:b1 and c2=:b2";
public static void main(String[] args) throws Exception
{
OracleDataSource ods = new OracleDataSource();
ods.setURL(url);
Properties props = new Properties();
props.put("user", user);
props.put("password", pwd);
props.put(OracleConnection.CONNECTION_PROPERTY_SQL_TRANSLATION_PROFILE,
PROFILE);
ods.setConnectionProperties(props);
Connection conn = ods.getConnection();
System.out.println("connection for SQL translation: "+conn);
try{
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println("Call:
oracle.jdbc.OracleTranslatingConnection.prepareStatement(sql, true)");
PreparedStatement trStmt = trConn.prepareStatement(primitiveSql, true);
trStmt.setInt(1, 1);
trStmt.setString(2, "A");
System.out.println("executeQuery for: "+primitiveSql);
ResultSet trRs = trStmt.executeQuery();
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.close();
trStmt.close();
}catch (Exception e) {
e.printStackTrace();
}
try{
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println("Call:
oracle.jdbc.OracleTranslatingConnection.prepareStatement(sql, false)");
PreparedStatement trStmt = trConn.prepareStatement(primitiveSql, false);
trStmt.setInt(1, 1);
trStmt.setString(2, "A");
System.out.println("executeQuery for: "+primitiveSql);
ResultSet trRs = trStmt.executeQuery();
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.close();
trStmt.close();
}catch (Exception e) {
System.out.println("expected Exception: "+e.getMessage());
}
try{
OracleTranslatingConnection trConn = (OracleTranslatingConnection) conn;
System.out.println("Call:
oracle.jdbc.OracleTranslatingConnection.prepareStatement(
sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, true)");
PreparedStatement trStmt = trConn.prepareStatement(
primitiveSql, ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY, true);
trStmt.setInt(1, 1);
trStmt.setString(2, "A");
System.out.println("executeQuery for: "+primitiveSql);
ResultSet trRs = trStmt.executeQuery();
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
System.out.println("trRs.beforeFirst and show resultSet again...");
trRs.beforeFirst();
while (trRs.next())
System.out.println("C1:"+trRs.getInt(1)+", C2:"+trRs.getString(2));
trRs.close();
trStmt.close();
}catch (Exception e) {
e.printStackTrace();
}
conn.close();
}
}6.2.5 getSQLTranslationVersions()
SQL翻訳時に問合せのすべての翻訳バージョンのマップを戻します。例外の場合、およびsuppressExceptionsがtrueの場合、マップ内の翻訳されたバージョンはNULLです。
構文
public Map<SqlTranslationVersion, String> getSqlTranslationVersions( String sql, boolean suppressExceptions) throws SQL Exception;
戻り値
問合せのすべての翻訳バージョンを含むマップ。返されるバージョンの詳細は、SqlTranslationVersionのenumを参照してください。
例外
suppressExceptionsがfalseの場合、問合せの翻訳で問題があると、このメソッドはSQLExceptionをスローします。
6.3 エラー翻訳構成ファイル
XML構成ファイル(パス)は、oracle.jdbc.sqlErrorTranslationFileプロパティの値として指定されます。このファイルには、エラーの翻訳情報が含まれます。これらのエラーは、サーバーへの接続が確立できないために、サーバー上で翻訳が行われない場合に生じます。エラー・メッセージは、接続を確立できないデータベースの状態を定義するタイプです。
構成XMLファイルの構造は、次のようにDTDで定義されます。
<!DOCTYPE LocalTranslationProfile[ <!ELEMENT LocalTranslationProfile (Exception+)> <!ELEMENT Exception (ORAError, ErrorCode, SQLState )> <!ELEMENT ORAError (#PCDATA)> <!ELEMENT ErrorCode (#PCDATA)> <!ELEMENT SQLState (#PCDATA)> ]>
ここで、
-
ORAErrorはint値で、Oracleエラーのエラー・コードを指定します。 -
ErrorCodeはint値で、ベンダーのエラー・コード(翻訳済コード)を指定します。 -
SQLStateはString値で、ベンダーのSQL状態を指定します。