8 JDBCアプリケーションのSQL翻訳のAPIリファレンス
oracle.jdbc
パッケージの一部であるAPI、特に、SQL翻訳の一翼を担うoracle.jdbc
の要素について詳しく見ていきます。JDBCアプリケーションを正常に移行するには、翻訳のプロパティやインタフェース、エラーの翻訳メカニズムを理解することが重要です。
関連項目:
-
Oracle Database JDBC Java APIリファレンスの
oracle.jdbc
パッケージのドキュメント一式
翻訳プロパティ
表8-1に、翻訳プロパティを示します。
表8-1 翻訳プロパティ
プロパティ | 説明 |
---|---|
翻訳プロファイルの名前を指定します。 |
|
SQLエラー翻訳ファイルのパスを指定します。 |
sqlTranslationProfile
プロパティoracle.jdbc.sqlTranslationProfile
は、翻訳プロファイルの名前を指定します。
宣言
oracle.jdbc.sqlTranslationProfile
定数
OracleConnection.CONNECTION_PROPERTY_SQL_TRANSLATON_PROFILE
定数の値は、oracle.jdbc.sqlTranslationProfile
です。これは、プロパティ名でもあります。
プロパティの値
値は文字列です。デフォルト値はありません。
注釈
プロパティsqlTranslationProfile
は、システム・プロパティまたは接続プロパティのいずれかとして設定できます。SQL翻訳を使用するには、このプロパティが必要です。このプロパティを設定する場合、その他で特に指定しないかぎり、接続で作成されるすべての文でSQL翻訳が有効になります。
sqlErrorTranslationFile
プロパティoracle.jdbc.sqlErrorTranslationFile
は、SQLエラー翻訳ファイルのパスを指定します。
宣言
oracle.jdbc.sqlErrorTranslationFile
定数
Oracle.connection.CONNECTION_PROPERTY_SQL_ERROR_TRANSLATION_FILE.
プロパティ値
値はパス名です。デフォルト値はありません。
例外
接続を確立する際のエラーによって、SQLExceptionが生じますが、有効な接続はありません。ただし、SQLエラー翻訳ファイルのパスは、システム・プロパティまたは接続プロパティのいずれかとして利用でき、エラーの翻訳に使用されます。
備考
このファイルは、接続の確立が失敗したときに生じるエラーの翻訳にのみ使用されます。接続が確立すると、このファイルは無視され、接続の確立後に生じるエラーの翻訳の詳細が含まれる場合でも考慮されません。プロパティsqlErrorTranslationFile
は、システム・プロパティまたは接続プロパティのいずれかとして設定できます。このファイルのコンテンツは、有効な接続がない場合に、Oracle SQLExceptionsを外部SQLExceptionsに翻訳する際に使用されます。
OracleTranslatingConnectionインタフェース
このインタフェースは、SQL翻訳をサポートするConnectionオブジェクトによってのみ実装されます。このインタフェースの主な目的は、翻訳接続から非翻訳文(preparedStatement
およびCallableStatement
を含む)を取得することです。
publicインタフェースoracle.jdbc.OracleTranslatingConnection
は、翻訳および非翻訳Statement
オブジェクトを作成するためのファクトリ・メソッドを定義します。
表8-2に、OracleTranslatingConnection
列挙を示します。
表8-2 OracleTranslatingConnectionの列挙
名前 | 説明 |
---|---|
マップのキーを提供します。 |
表8-3に、OracleTranslatingConnection
メソッドを示します。
表8-3 OracleTranslatingConnectionメソッド
名前 | 説明 |
---|---|
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
|
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
|
SQLを翻訳するオプションまたは翻訳しないオプションを指定して |
|
SQL翻訳時に問合せのすべての翻訳バージョンのマップを戻します。 |
SqlTranslationVersion
SqlTranslationVersion
列挙値は、getSQLTranslationVersions()メソッドのキーを指定します。
構文
public enum SqlTranslationVersion { ORIGINAL_SQL, JDBC_MARKER_CONVERTED, TRANSLATED }
次の表では、SqlTranslationVersion
のすべての列挙値と、それぞれの列挙値の説明を示します。
メンバー名 | 説明 |
---|---|
|
元のベンダーに固有のSQLを指定します。 |
JDBC_MARKER_CONVERTED |
JDBCパラメータ・マーカー('?')がOracleスタイルのパラメータ・マーカー(':b<n>')で置き換えられるように指定します。このため、連続する'?'は、 |
TRANSLATED |
サーバーから戻される翻訳済問合せを指定します。 |
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');
例8-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(); } }
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)}');
例8-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(); } }
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');
例8-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(); } }
getSQLTranslationVersions()
SQL翻訳時に問合せのすべての翻訳バージョンのマップを戻します。例外の場合、およびsuppressExceptions
がtrueの場合、マップ内の翻訳されたバージョンはNULL
です。
構文
public Map<SqlTranslationVersion, String> getSqlTranslationVersions( String sql, boolean suppressExceptions) throws SQL Exception;
戻り値
問合せのすべての翻訳バージョンを含むマップ。返されるバージョンの詳細は、SqlTranslationVersionのenum
を参照してください。
例外
suppressExceptions
がfalseの場合、問合せの翻訳で問題があると、このメソッドはSQLException
をスローします。
エラー翻訳構成ファイル
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状態を指定します。