Comments
Description
Transcript
JDBC SQLJ
Page 1 1 JDBC/SQLJの 概要及び開発技法 Page 2 2 JDBC/SQLJの概要及び開発技法 目次 l JDBC – – – – l JDBC概要 3つのJDBC ドライバ JDBCチュートリアル JDBCサンプル SQLJ – – – – SQLJ概要 SQLJの構成 SQLJを使用した開発 SQLJサンプル Page 3 3 JDBC概要 JDBCとは? l l JDBC とは、リレーショナル・データベースへの 問い合わせと更新を行うための標準Javaクラス ライブラリ JDBC の目的 – 特定のRDBMSに依存しないプログラムを記述 l JDBC はODBCに準拠 l JDBC で何ができるか – データベースとの接続の確立 – SQL文の送信、実行結果の処理 JDBCは、SQL 文を実行するための標準 Java API です。これは、Javaプログラミング言語で書かれたク ラスとインタフェースのセットで構成されます。 JDBCは、Java のアプリケーション開発者のための標準 API を提供し、特定のRDBMSに依存しないデー タベースアプリケーションの作成を可能にします。 Java は、強固で安全であり、データベースアプリケーションのための非常に優れた基盤言語です。必 要なのは、Java アプリケーションが多種多様なデータベースとやり取りするための方法です。JDBC は、 これを行うための機構です。 型をサポートしました。 JDBCはODBCをベースにJavasoft によってモデル化され、SQL99のシンタックス・ JDBCはベンダ固有の拡張を考慮に入れており、Oracle ではいろいろな拡張をしています。 Page 4 4 JDBC概要 OracleのJDBCドライバ l Oracleは3つのJDBC ドライバを提供 – JDBC OCI ドライバ(クライアント側、TypeⅡ) – JDBC Thin ドライバ(クライアント側、TypeⅣ) – サーバ・ドライバ(サーバ側) l 標準に準拠 – JDBC2.0に準拠 Ÿ 標準のJDBC APIに加え、独自の機能をサポート Oracle は2つのクライアント用ドライバと、1つのサーバ用ドライバを提供しています。 クライアント側およびサーバ側のOracle JDBCドライバは、同じ機能を提供し、標準規格に準拠します。 また、標準のJDBC API に加え、独自の機能をサポートします。Oracle の JDBC ドライバが独自にサポー トしているものには次のようなものがあります。 ・ROWID、REFCURSOR、object-relational typesのような Oracle特有のデータ型 ・JavaとPL/SQL のストアド・プロシージャへのアクセス ・全てのオラクル・ キャラクタ・セットのサポート Page 5 5 JDBC概要 JDBC2.0の新機能 Ÿ バッチ更新 Ÿ ResultSetの機能拡張 – スクロール可能、更新可能なResultSet Ÿ フェッチサイズ、行プリフェッチ Ÿ JNDI によるデータベースのネーミング Ÿ コネクション・プーリングのサポート Ÿ 分散トランザクション/XA Ÿ SQL3(SQL99) で扱われる各種データ型のサポート JDBC2.0で、以下の新機能が使用可能になりました。 • バッチ更新 •ResultSetの機能拡張(スクロール可能、更新可能なResultSet) •Javaオブジェクトの永続化 • フェッチサイズ、行プリフェッチ •JNDI によるデータベースのネーミング • コネクション・プーリングのサポート • 分散トランザクション /XA •SQL3(SQL99)で扱われる各種データ型のサポート Page 6 6 JDBC/SQLJの概要及び開発技法 目次 l JDBC – – – – l JDBC概要 3つのJDBC ドライバ JDBCチュートリアル JDBCサンプル SQLJ – – – – SQLJ概要 SQLJの構成 SQLJを使用した開発 SQLJサンプル Page 7 7 3つのJDBCドライバ OCIドライバ l l l 主な対象:C/S型 Javaアプリケーション及び中 間層Javaアプリケーション JDBC の呼び出しをOCI の呼び出しに変換し 、Net8経由でデータベースに接続する。 特徴 – OCI libやNet8などのOracle クライア ントのインストールが必要 – パフォーマンスが良い – 全ての Net8アダプタを使用可能 Java Program JDBC OCI Driver OCI C Library Net8 SQL Engine PL/SQL Engine インターフェース(OCI )を使うためのJDBCインターフェースです。Cの OCI ドライバはオラクル・コール・ エントリ・ポイントを呼び出すため、プラットフォームに依存します。 OCI ドライバには、Net8 を含む、Oracle クライアントのインストールが必要です。 このドライバは、OCI を通してオラクル・ データベースとやりとりするため、Net8で接続できる全てのバー ジョンのオラクル・データベースと接続できます。また、ローカル接続( BEQ )とインストールされた全ての Net8 アダプタ(IPC、Named Pipes、TCP/IP、IPX/SPX)をサポートします。 Page 8 8 3つのJDBCドライバ Thinドライバ l l l l 主な対象:アプレット ThinドライバがTCP/IPバージョンのNet8を独 自に実現して、データベースに接続する。 OCIドライバと同様の機能拡張 特徴 – クライアント側でのインストールが必要 ない – Thinドライバのダウンロードに時間が かかる – Net8 TCP/IPプロトコルのみサポート Java Program JDBC Thin Driver Java Sockets Net8 TCP/IP Listener SQL Engine PL/SQL Engine Thin ドライバは、Java アプリケーションでの利用も可能ですが、事前にセットアップを必要としないので、 Java Applet での利用には理想的です。機能的にもOCI ドライバと同様の拡張がされております。 Thin ドライバは、TCP/IPバージョンのOracle Net8 を独自に実現(Java Socket の上にNet8及び セットやデータの形式を必要に TTC(Two-Task Common: クライアントとサーバ間の通信でキャラクタ・ 応じて変換するレイヤー) をエミュレート) しています。このドライバではTCP/IP プロトコルのみがサポート されます。またTNS リスナーがデータベース・ サーバ上のTCP/IPソケットをリスニングする必要もあります。 Applet で利用される場合の動作 1. HTMLページからブラウザにJava Applet をダウンロード 2. JDBC Thin ドライバはApplet と共にブラウザにダウンロードされる 3. Applet が動作する時、直接、Net8 接続を確立 Page 9 9 3つのJDBCドライバ サーバ・ドライバ l l l 主な対象:Oracle8i内のJavaVM で動作し、デ ータベースと通信するJavaプログラム ネットワークを介してではなく、関数コールを使 用し、SQLエンジンにアクセスする。 Java Program 特徴 – ドライバ、JavaVM 、データベース、 KPRB C ライブラリ、SQLエンジン は全て同じアドレス空間で動作 – デフォルトセッションを使用 Java Engine JDBC Server Driver KPRB C Library SQL Engine PL/SQL Engine サーバ・ドライバの利用は、サーバ側でのみ可能です。サーバ・ドライバは、Java Stored Procedure 、 CORBA、Enterprise JavaBeans (EJB)等のデータベースに格納されたJava プログラムでSQL, PL/SQLを 利用することを可能とします。 サーバ・ドライバもクライアント側ドライバと同様の機能、拡張をサポートします。 サーバ・ドライバはデータベース内で動作するように最適化されており、データベースおよび SQLエン ジンと同じアドレス空間で動作します。 SQL エンジンへのアクセスは関数コールであり、ネットワークは使 用しません。これにより、JDBCプログラムのパフォーマンスが向上し、SQLエンジンへのアクセスにリモー トNet8 コールを実行するよりもはるかに高速です。 サーバ・ドライバを使用するには、すでに「 接続された」状態になっており、このドライバはそのデフォル トのセッション内で動作します。 Page 10 10 3つのJDBCドライバ 最適なドライバの選択 l OCIドライバ – C/S Javaアプリケーション、中間層Javaアプリケーション – パフォーマンスを望む場合 l Thinドライバ – アプレット – 高い移植性を望む場合 l サーバ・ドライバ – Oracle8i内でのプログラム (Java Stored Procedure, CORBA ・ EJB Objectなど) Java アプリケーションやApplet で使用する JDBCドライバを選択する際に、次の点を考慮してください。 ・Applet を作成する場合は、Thin ドライバを使用してください。OCI ドライバは実行する環境 での事前のインストールが必要ですので、選択できません。 ・高い移植性を望む場合は、Thin ドライバを使用します。Thin ドライバを利用すると、アプリケー ションとアプレットのどちらからでもOracle データベースに接続できます。 ・アプリケーションのパフォーマンスを重視する場合は、OCI ドライバを使用してください。 ・Oracle8i 内で動作するプログラムの場合は、サーバ・ドライバを使用してください。 Page 11 11 JDBC/SQLJの概要及び開発技法 目次 l JDBC – – – – l JDBC概要 3つのJDBC ドライバ JDBCチュートリアル JDBCサンプル SQLJ – – – – SQLJ概要 SQLJの構成 SQLJを使用した開発 SQLJサンプル Page 12 12 JDBCチュートリアル JDBCを使用するための環境 l CLASSPATH – [Oracle Home]/jdbc/lib/classes12.zip – NLSを使用する場合は下記も追加 [Oracle Home]/ jdbc/lib/nls_charset12.zip l OCIドライバ – Solaris: LD_LIBRARY_PATH=[Oracle Home]/lib – Windows NT: PATH=[Oracle Home]¥bin l Thinドライバ – CLASSPATHの設定のみ クライアント側の JDBCドライバ用に設定する環境変数について説明します。 インストールした JDBCドライバ用のCLASSPATH を指定する必要があります。使用しているJDK バージョ ンに応じて、適切なCLASSPATH を指定してください。 Thin ドライバの場合は、CLASSPATH 以外の環境変数を指定する必要はありません。 OCI ドライバを使用する場合には、ライブラリー・パス環境変数に次の値を指定する必要もあります。 Solaris LD_LIBRARY_PATH に[Oracle Home]/lib を追加 Windows NT PATH に[Oracle Home]¥binを追加 Page 13 13 JDBCチュートリアル JDBCを使用したプログラムの流れ l クエリーの実行手順 1. パッケージのインポート 2. JDBCドライバの登録 3. データベースへの接続 4. Statementオブジェクトの作成 5. クエリーの実行 6. 問い合わせ結果の処理 7. ResultSet、Statementオブジェクトのクローズ 8. データベースとの接続終了 Oracle JDBCドライバの起動および実行方法についてチュートリアルの形式で説明します。チュートリア ルを実行することにより、クライアントからデータベースへの接続および問い合わせを行うJDBC Java コー ドを作成できます。 Page 14 14 JDBCチュートリアル JDBCを使用したプログラムの作成(1) 1. パッケージのインポート import java.sql.* JDBCパッケージ – オラクル独自の拡張機能を使用する場合は下記も追加 import oracle.jdbc.driver.* import oracle.sql.* 2. JDBC ドライバの登録 – JDBCドライバはDriverManagerに登録しなければならない 例:DriverManager.registerDriver( new oracle.jdbc.driver.OracleDriver()); 1. パッケージのインポート 使用する JDBCドライバの種類に関わらず、JDBC パッケージの import 文を記述する必要があ ります。Oracle JDBCドライバの提供する拡張機能を使用する場合、Oracleパッケージを追加 する必要があります。 2. JDBCドライバの登録 使用するドライバをアプリケーションに登録するためのコードを記述する必要があります。この 例では、DriverManager クラスの static なregisterDriver() メソッドを使っています。別の方法と して、java.lang.Class クラスのforName() メソッドを使用して JDBCドライバをロードすることも可 能です。 例:DriverManagerの1文を次の様に変更します。 try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (ClassNotFoundException e) {...} ※ Class.forName() を使用する場合には例外処理を考慮しなくてはなりません。 Class.forName() メソッドを利用した場合は、実行時に動的にロードされるようになるため、次の ような利点があります。 ・ロードするクラス名を文字列で指定可能であるため、プログラムを修正することなく JDBCドライバを任意に選択するようにする事が可能 ・プログラム作成時に JDBC ドライバが無くともアプリケーションの作成が可能 JDBCドライバは、アプリケーション上で1度だけ登録します。 Page 15 15 JDBCチュートリアル JDBCを使用したプログラムの作成(2) 3. データベースへの接続 – 接続するには、DriverManager を使用 – getConnection(String URL,String user,String password); – URLの書式は、jdbc:oracle:<drivertype>:@<database> – 例 (OCI):Connection conn = DriverManager.getConnection("jdbc:oracle:oci8:@ myHostString", "scott", "tiger"); – 例 (Thin) :Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@myhost:1521:orcl", "scott", "tiger"); 4. Statementオブジェクトの作成 – 例:Statement stmt = conn.createStatement(); 3. データベースへの接続 データベースへの接続を、DriverManager クラスの static な getConnection() メソッドを使用し てオープンします。このメソッドは Connection クラスのオブジェクトを返します。 データベースURL 、ユーザID、パスワードを指定する書式 getConnection(String URL, String user, String password); URLの書式は、”jdbc:oracle:type:@<database>”となります。 type は、thin もしくは oci8 を指定します。 database は、OCIドライバの場合はTNS名を指定し、thinドライバの場合は”host名:リ スナーポート:SID”を指定します。 ユーザID 、パスワードをデータベースURLに含む書式 getConnection(String URL); OCIドライバでデフォルト接続をする場合は、次のように記述します。 Connection conn = DriverManager.getConnection( “jdbc:oracle:oci8:scott/tiger@”); 4. Statement オブジェクトの作成 データベースへ接続すると Connection オブジェクトを作成します。その後、Connection クラス の createStatement() メソッドで、Statement オブジェクトを作成します。 Page 16 16 JDBCチュートリアル JDBCを使用したプログラムの作成(3) 5. クエリーの実行 – StatementオブジェクトのexecuteQuery()メソッドを使 用 – executeQuery()メソッドは、1つのSQL問い合わせを 実行し、ResultSetオブジェクトを返す – 例:ResultSet rset = stmt.executeQuery("select * from EMP"); 5. クエリーの実行 データベースへの問い合わせを行う場合、Statement クラスの executeQuery() メソッドを使用し ます。このメソッドは、入力として SELECT 文を受け取り、ResultSet クラスのオブジェクトを返し ます。 INSERT文, UPDATE文 , DELETE 文 , DDL文の実行 – executeUpdate()メソッドを使用 例: INSERT stmt.executeUpdate( “insert into EMP(EMPNO, ENAME) values(100, ’jserver’”); UPDATE stmt.executeUpdate( “update EMP set SAL = 10000 where EMPNO = 100”); DELETE stmt.executeUpdate(“delete from EMP where SAL > 10000”); DDL 文 stmt.executeUpdate( “create table test(id number(3), name(12))”); Page 17 17 JDBCチュートリアル JDBCを使用したプログラムの作成(4) 6. 問い合わせ結果の処理 – ResultSet オブジェクトは、SQL問い合わせから返される結果 セットを管理 – カーソルをサポート – getXXX() メソッドを用いてデータを取りだし、結果を該当する Java型にマッピング – 例: while(rset.next()) { String ename = rset.getString(1); … } 6. 問い合わせ結果の処理 クエリーの実行後は、ResultSet オブジェクトの next() メソッドを使って、結果を反復します。こ のメソッドは、結果セットを行ごとにループして、結果セットの最後に達するとそれを検出します。 next() メソッドは結果セットの最後に達するとfalse を返します。 データを取り出すには、ResultSet オブジェクトの getXXX() メソッドを使用します。引数には、 カラムの位置 もしくは カラムの名前 を指定してデータの取り出しが可能です。ここでのXXX には、Java のデータ型が対応します。この例では String 型でカラムの位置を指定してデータ を取りだしています。良く使用されるものには下記があります。 メソッド Javaデータ型 SQLデータ型 getString() getBigDecimal() getByte() getDate() getInt() getLong() java.lang.String java.math.BigDecimal byte java.sql.Date int long VARCHAR2 NUMBER CHAR DATE NUMBER NUMBER Page 18 18 JDBCチュートリアル JDBCを使用したプログラムの作成(5) 7. ResultSet, Statementオブジェクトのクローズ – ResultSet、Statementオブジェクトは、使い終わった ら明示的にクローズしなくてはならない – 例:rset.close(); stmt.close(); 8. データベースとの接続終了 – 作業が完了したら、データベースとの接続を終了し なくてはならない – 例:conn.close(); 7. ResultSet, Statement オブジェクトのクローズ ResultSet とStatement オブジェクトの使用後に、明示的にこれらをクローズする必要がありま す。これは、JDBCドライバを使用して作成したすべてのResultSet および Statement オブジェク トに適用されます。 JDBCドライバではリソースは暗黙的に解放されません。そのため、クリーンアップ・ルーチンは、 ResultSet および Statement クラスの close() メソッドを使って実行します。明示的にオブジェクト のクローズをしないと、深刻なメモリ・リークが発生する場合があります。ResultSetオブジェクト のクローズを行うと、データベース内の対応するカーソルが解放されます。 8. データベースとの接続終了 作業が完了したら、データベースへの接続を終了する必要があります。これは、Connection ク ラスの close() メソッドを使って実行します。クライアント側でConnection クラスの close() メソッド が呼ばれるまで、データベースとのセッションは保持されます。 Page 19 19 JDBC/SQLJの概要及び開発技法 目次 l JDBC – – – – l JDBC概要 3つのJDBC ドライバ JDBCチュートリアル JDBCサンプル SQLJ – – – – SQLJ概要 SQLJの構成 SQLJを使用した開発 SQLJサンプル Page 20 20 JDBC サンプル・ソース import java.sql.*; class emp { public static void main(String args[]) throws SQLException { // JDBCドライバのロード、ドライバの登録 DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // データベースへの接続 Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@myhost:1521:orcl", "scott", "tiger"); // Statementオブジェクトの作成 Statement stmt = conn.createStatement(); // クエリーの実行 (EMPテーブルの全てのカラム) ResultSet rset = stmt.executeQuery("select * from EMP"); // メタデータの取得 ResultSetMetaData rsmd = rset.getMetaData(); // カラム数の取得 int numCols = rsmd.getColumnCount(); // カラム名の出力 for (int i=1; i<=numCols; i++) { if (i > 1) System.out.print(","); System.out.print(rsmd.getColumnLabel(i)); } System.out.println(""); // 問い合わせ結果の処理 while (rset.next()) { for (int i=1; i<=numCols; i++) { if (i > 1) System.out.print(","); // 問い合わせ結果の出力 System.out.print(rset.getString(i)); } System.out.println(""); } // ResultSet、Statementオブジェクトのクローズ rset.close(); stmt.close(); // データベースとの接続終了 conn.close(); } } Page 21 21 JDBC/SQLJの概要及び開発技法 目次 l JDBC – – – – l JDBC概要 3つのJDBC ドライバ JDBCチュートリアル JDBCサンプル SQLJ – – – – SQLJ概要 SQLJの構成 SQLJを使用した開発 SQLJサンプル Page 22 22 SQLJ概要 SQLJとは? l l 静的なSQL操作をJava コードに埋め込むことが 可能 何ができるか – 埋め込みSQLの構文チェック – データ型のチェック – セマンティクスの確認 SQLJ はPro*Cのようなプリコンパイラと概念的に似ていて、Java プログラムにSQL文を埋め込むことが できます。トランスレータ( プリプロセッサ)を実行し、SQLJコードからJDBCコールを含むJavaコードを生 成します。SQLJでは全てのベンダのJDBCドライバが使用可能です。 SQL文を Javaコードに直接埋め込む SQLJ方式は、JDBC方式より扱いやすく簡潔です。 SQLJを使用 すると、データベース接続を必要とするJavaプログラムの開発費とメンテナンス費を節約できます。 SQLJ トランスレータでは、次のチェックを行います。 ・埋め込み SQLの構文チェック ・データ型のチェック (Java とSQL 間で型変換が適切に行われることの確認) ・セマンティクスの確認 ( SQL の構文とデータベース・スキーマの比較) ※ JDeveloperではSQLJ アプリケーションの開発・デバッグ等の開発環境を提供 Page 23 23 SQLJ概要 OracleのSQLJ l 標準に準拠 l Oracleの拡張 – 標準以外のデータ型のサポート – データベース内のJavaVM での実装 SQLJは、Oracle、IBM、Tandem 、Sybase、Infomix、Javasoft をはじめとするベンダーで共同開発されて います。ANSI/ISOに SQLJ 言語仕様を提出し、スタンダードとしての地位を確立しています。 Oracle SQLJ では、ANSI SQLJ標準以外のSQL文も使用できます。ANSI SQLJ標準は、SQL92 のみを 規定していますが、拡張も許容しています。Oracle SQLJでは、Oracleの SQL言語を使用できます。デー タ型は、LOB(BLOB, CLOB, BFILE) 、ROWID 、REF CURSORなどの Oracle 固有のデータ型もサポー トされます。 また、データベース内のJava VMでもSQLJ を実装することにより、Java のストアド・プログラムでの使用 が可能となっています。 Page 24 24 SQLJ概要 JDBC vs. SQLJ JDBC SQLJ java.sql.PreparedStatement stmt; ResultSetIterator results; ResultSet results; #sql results = stmt = conn.prepareStatement {SELECT ename FROM emp (“SELECT ename FROM emp WHERE sal > :salparam WHERE sal > ? AND deptno = ?”); AND deptno = :deptnoparam}; stmt.setInt(1, salparam); stmt.setInt(2, deptnoparam); results = stmt.executeQuery(); SQLJコードは JDBC コードと比較するとはるかに簡潔で生産的です。 記述するコードの量が増えると、当然エラーの確率も上がります。 SQLJは下記の方法で開発者の生産性を改善します。 •JDBCよりコンパクトなコード • SQL 文を直接埋め込む • SQL 文中でJavaのバインド変数や表現を使用可能 • default connectionをサポート • JDBC Statementオブジェクトを意識する必要がない • 早い段階でのチェック • JDBCでは実行時まで確認できなかったSQL文の構文チェック、データ型の チェック等を開 発時に行う Page 25 25 SQLJ概要 JDBCとSQLJ l JDBC+SQLJ は補完的な関係 – SQLJは静的SQLのためのより簡潔なシンタックスを 提供 – 動的SQLはJDBC で記述 – 1つのプログラムでSQLJとJDBCの混在が可能 SQLJ は JDBCと比較して簡潔なシンタックスを提供しますが、これは静的 SQLのためのものであり、動 的 SQLでは使用できません。動的 SQLを使用するには JDBCで記述する必要があります。 そのため、SQLJ では、JDBC との混在が可能なように考慮されています。SQLJ とJDBCが連係動作を するために、SQLJ 接続コンテキストからJDBC接続への変換とSQLJイテレータから JDBC ResultSet への変換が可能となっております。 ※ JDBC ドライバはどのベンダーのドライバでも使用できます。ただし、Oracle 固有の データ型や機 能を使用する場合は、Oracle JDBCドライバを使用してください。 Page 26 26 JDBC/SQLJの概要及び開発技法 目次 l JDBC – – – – l JDBC概要 3つのJDBC ドライバ JDBCチュートリアル JDBCサンプル SQLJ – – – – SQLJ概要 SQLJの構成 SQLJを使用した開発 SQLJサンプル Page 27 27 SQLJの構成 SQLJのコンポーネント l SQLJのコンポーネント – トランスレータ – ランタイム l SQLJ SQLJ Application Application SQLJ SQLJ runtime runtime SQLJプロファイル – SQL操作に関する詳細情報 Any Any JDBC JDBC Driver Driver Any RDBMS Oracle SQLJ は、次の2 つの主要コンポーネントで構成されています。 Oracle SQLJトランスレータ このコンポーネントは、SQLJコードからJava コードを生成するためのプリプロセッサ(プリコンパ イラ) です。 SQLJコードのファイルの拡張子は、必ず .sqlj にしましょう。 Oracle SQLJランタイム エンド・ ユーザが SQLJ アプリケーションを実行する際に、このコンポーネントが起動します。 このコンポーネントは JDBCドライバを介してデータベースにアクセスします。このアクセス方法 は、汎用SQLJ標準の規定ではなく、Oracle SQLJランタイムの要件です。 コンポーネントは、純粋な Java コードから成るThin レイヤーで、JDBCドライ SQLJ ランタイム・ バの上で動作します。 SQLJ プロファイル SQLJプロファイルは、シリアライズされたJavaオブジェクトであり、SQLJトランスレータによって 生成されます。プロファイルの内容は、SQLJ コードに埋め込まれているSQL 操作に関する情 報やアクセスするデータの型やモードに関する情報で、プログラム実行時にランタイム・ コンポー ネントより使用されます。 SQLJプロファイルの拡張子は通常 .ser になります。 Page 28 28 SQLJの構成 SQLJトランスレーション処理 SQLJ コード SQLJ トランスレータ JDBC コールを 含む Java コード Java コンパイラ Java クラス ファイル Oracle8i l l トランスレータが、JDBCコールを含む標準的な Java コードを生成 早い段階での SQL文、データ型等のチェック SQLJ アプリケーションを作成するために、開発者はまず、SQLJ トランスレータを用いて SQLJ コード からJDBCコールを含む標準的な Java コードを生成します。開発者は、SQLJ オプションの設定により、 オンライン・チェックまたはオフライン・チェックを指定できます。オンライン・チェックでは、データベース に接続され、アプリケーションで使用されるデータベース表、ストアド・ プロシージャ、SQLの構文などが すべて問題ないかどうかが検証されます。 SQLJ プログラムの変換処理は次のようなステップで処理されます。 1. SQLJ トランスレータを起動 2. sqlj ファイル内のコード解析と構文チェック SQLJ 構文が検証され、セミコロンの抜け、中カッコの対の抜け、明らかな型の不一致 などがチェックされます。 3. セマンティクス・チェック 埋め込み SQL文のセマンティクスがチェックされます。 コールに変換し、Java コードと SQLJプロファイルを生成 4. SQL 操作を SQLJ ランタイム・ コンパイラ(通常は を起動し、ステッ 5. Java Sun MicrosystemsのJDKで提供される標準 javac) プ4で生成された Javaコードがコンパイルされます 6. プロファイルのカスタマイズ ベンダー固有のデータ型や機能を使用できるようにします Page 29 29 JDBC/SQLJの概要及び開発技法 目次 l JDBC – – – – l JDBC概要 3つのJDBC ドライバ JDBCチュートリアル JDBCサンプル SQLJ – – – – SQLJ概要 SQLJの構成 SQLJを使用した開発 SQLJサンプル Page 30 30 SQLJを使用した開発 SQLJを使用するための環境 l CLASSPATH – JDBCでの設定 – [Oracle Home]/sqlj/lib/translator.zip – SQLJアプリケーションの実行には、ランタイム・クラ スが必要です。ランタイム・クラスは次のファイルに 含まれています。 [Oracle Home]/sqlj/lib/runtime.zip l PATH – [Oracle Home]/bin Oracle SQLJ を使用する前提条件として、下記があります。 • システム上で標準 Java環境が必要です。(通常はSun MicrosystemsのJDK ) JDK のバージョンは1.1.x と1.2.x をサポートします。1.0.2は未サポートです。 • 使用している環境で、JDBCアプリケーションを実行できる必要があります。 java.sql JDBCインターフェースを実装するJDBCドライバが必要です。 JDBCドライバを使用してアクセス可能なデータベースが必要です。 Oracle SQLJ を使用するには、CLASSPATH とPATHを設定する必要があります。 Page 31 31 SQLJを使用した開発 SQLJ開発ステップの流れ l 開発ステップ 1. SQLJプログラムを記述 2. SQLJプログラムを変換 3. SQLJアプリケーションの実行 Page 32 32 SQLJを使用した開発 SQLJアプリケーションの開発ステップ(1) l SQLJプログラムの記述 – SQLJ句の使用 – JavaにSQL文を埋め込むための標準的な構文 で記述される実行可能なSQLJ文 – 全ての SQLJ句は‘#sql’で始まる – {}内にSQL文を記述する – 全ての SELECT文、DML文、DDL文が埋め込 み可能 – SQL文中でJavaの変数を使用 – バインド変数は‘:’の後に続ける SQLJ プログラムでのSQL文の例を示します。 基本的な SQL #sql { INSERT INTO EMP(ENAME) VALUES (’Joe’) }; PL/SQLブロック #sql { DECLARE n NUMBER; BEGIN n := 1; WHILE n <= 100 LOOP INSERT INTO EMP(EMPNO) VALUES (2000 + n); n := n + 1; END LOOP; END; }; バインド変数 String name = “SMITH“; double salary = 25000.0; ... #sql { UPDATE EMP SET SAL = :salary WHILE ENAME = :name }; Page 33 33 SQLJを使用した開発 SQLJアプリケーションの開発ステップ(2) l SQLJプログラムの変換 – SQLJトランスレータを実行 – コマンドラインで実行 – SQLのチェックを行う – オプションの指定 l SQLJアプリケーションの実行 2. SQLJ プログラムを変換 SQLJ コードが完成したら、SQLJ トランスレータを実行して SQLJプログラムをJava プログラムに変換し ます。例えば、ソース・ファイルが sample.sqlj であった場合、下記のようにコマンドラインから実行します。 > sqlj sample.sqlj 例えば下記のようなコードではオンライン・ チェックで不整合エラーが発生します。 Date d = new Date(1993, 3, 11); #sql {insert into EMP values (:d)} ※ 同じ内容のJDBC プログラムは実行時にエラーが発生します。 オプションの指定は、コマンドラインまたはプロパティ・ファイルにて行います。例えば、プロパティ・ ファ イルでユーザー名を指定し、コマンドラインでパスワードを指定する事ができます。 3. SQLJ アプリケーションの実行 トランスレーション処理で生成されたSQLJ アプリケーションを実行します。アプリケーションからSQLJ ランタイムが呼び出されます。SQLJ ランタイムは該当するSQL操作をプロファイルから読み込みます。 その後、SQLJ ランタイムが JDBCドライバを呼びだし、SQL操作を JDBC ドライバに渡します。 Page 34 34 SQLJを使用した開発 SQLJでの検索 l SQLJイテレータの使用 – 名前指定イテレータ – 位置指定イテレータ – イテレータの使用手順 1.イテレータの宣言 2.イテレータ・クラスのインスタンスを定義 3.SELECT文を使用し、イテレータ変数に結果を 取り込む 4.イテレータの検索列にアクセスする 5.イテレータを閉じて、リソースを解放 SQLJ プログラムで複数行の問い合わせ結果を処理するには、SQLJ イテレータが必要です。イテレー タには宣言の方法で名前指定イテレータと位置指定イテレータの2種類存在します。それぞれに利点 があり、使用目的も異なります。 名前指定イテレータは、SELECTフィールドとイテレータ列は名前で一致する必要があります。そのた め、問い合わせのカラム順を意識する必要がありません。データが誤った列に取り込まれる事がないた め、エラーが少なくなります。データの取り込みにnext() メソッドを使用します。 位置指定イテレータは、他の埋め込みSQL言語と同様のパラダイムや構文が使用可能です。例えば、 データの取り込みにFETCH INTO 構文を使用します。データを名前ではなく、位置で取り込むため、問 い合わせのカラム順に注意する必要があります。 それぞれの例については、次ページを参照してください。 Page 35 35 イテレータの例 名前指定イテレータ // イテレータの宣言 #sql iterator EmpIter(String ENAME, double SAL); ... // イテレータ・クラスのインスタンスを定義 EmpIter emps; #sql emps = { select SAL, ENAME from EMP }; // 結果の操作 while(emps.next()) { String ename = emps.ENAME(); // “ENAME”, “SAL”は宣言と完全に一致 double sal = emps.SAL(); // 大文字です。 “ename”, “sal”ではありません。 ... } emps.close(); 位置指定イテレータ // イテレータの宣言 #sql iterator EmpIter(String, double); ... // ホスト変数の定義 String name = null; double salary = 0; // イテレータ・クラスのインスタンスを定義 EmpIter emps; #sql emps = { select ENAME, SAL from EMP }; // 結果の操作 while(true) { #sql { FETCH :emps INTO :name, :salary }; // endFetch()メソッドでデータの終わりに達したかどうかを確認します。 // これは、必ずFETCH INTO文の後で行う必要があります。 if (emps.endFetch()) break; System.out.println(“Name is “ + name); ... } emps.close(); Page 36 36 SQLJを使用した開発 プログラミング上の注意事項 l 名前の制限 l NULLの処理 l 例外処理 l トランザクション制御 プログラミング上の主な注意事項について説明します。 名前の制限 文字列 “__sJT_“は、SQLJ で生成した変数名のプレフィックスとして予約されています。また、 java 、sqlj、oracle などのアプリケーションで使用するパッケージ名はクラス名として使用できま せん。 NULLの処理 Java の基本型(int, double, float など)は規約上、NULL 値をとることができません。データベー スからのデータ受信時に、SQLのNULLが Java のNULLに変換されます。SQLのNULLが受 信されそうな場合は、Java の基本型を出力変数として使用しないでください。基本型のかわり に、次のラッパークラスを使用します。 •java.lang.Boolean •java.lang.Byte •java.lang.Short •java.lang.Integer •java.lang.Long •java.lang.Double •java.lang.Float 例外処理 SQLJ プログラムは JDBC コールを含む Java コードです。したがって、SQLJ でも SQLJ 構文を 含むブロックで適切な例外処理を組み込む必要があります。 トランザクション処理 コミットおよびロールバックは、開いている結果セットとイテレータには反映されません。内容は SELECT文を実行したときの状態が引き続き反映されています。(データベース・アプリケーショ ンでの一般的な注意事項です) Page 37 37 JDBC/SQLJの概要及び開発技法 目次 l JDBC – – – – l JDBC概要 3つのJDBC ドライバ JDBCチュートリアル JDBCサンプル SQLJ – – – – SQLJ概要 SQLJの構成 SQLJを使用した開発 SQLJサンプル Page 38 38 SQLJ サンプル・ソース import java.sql.*; import sqlj.runtime.*; import oracle.sqlj.runtime.Oracle; class sample { public static void main(String args[]) throws SQLException { // オラクルへの接続 'sqlj.properties'でスキーマの指定などを行う Oracle.connect(sample.class, "sqlj.properties"); // ResultSetオブジェクトへ変換するためのイテレータ ResultSetIterator rsiter; #sql rsiter = { SELECT * FROM EMP }; // ResultSetオブジェクトを取得 ResultSet rset = rsiter.getResultSet(); // メタデータの取得 ResultSetMetaData rsmd = rset.getMetaData(); // カラム数の取得 int numCols = rsmd.getColumnCount(); // カラム名の出力 for (int i=1; i<=numCols; i++) { if (i > 1) System.out.print(","); System.out.print(rsmd.getColumnLabel(i)); } System.out.println(""); // 問い合わせ結果の処理 while (rset.next()) { for (int i=1; i<=numCols; i++) { if (i > 1) System.out.print(","); // 問い合わせ結果の出力 System.out.print(rset.getString(i)); } System.out.println(""); } // ResultSetIteratorオブジェクトのクローズ // ResultSetもクローズされます rsiter.close(); } } Page 39 39 SQLJ プロパティ・ファイル (sqlj.properties ) ### ### 詳細は、『 SQLJ開発者ガイドおよびリファレンス』 マニュアル 「第8章 トランスレータのコマンド行とオプション」を参照して下さい。 ### ### ### ### Settings to establish a database connection for online checking ### ### turn on checking by uncommenting user ### or specifying the -user option on the command line sqlj.user=scott sqlj.password=tiger ### add additional drivers here sqlj.driver=oracle.jdbc.driver.OracleDriver ### Oracle JDBC-OCI7 URL #sqlj.url=jdbc:oracle:oci7:@ ### Oracle JDBC-OCI8 URL sqlj.url=jdbc:oracle:oci8:@ ### Oracle JDBC-Thin URL #sqlj.url=jdbc:oracle:thin:@<host>:<port>:<oracle_sid> #sqlj.url=jdbc:oracle:thin:@localhost:1521:orcl ### Warning settings ### Note: All settings must be specified TOGETHER on a SINGLE line. ### Report portability warnings about Oracle-specific extensions to SQLJ #sqlj.warn=portable ### Turn all warnings off #sqlj.warn=none ### Turn informational messages on #sqlj.warn=verbose ### Online checker ### # JDBC-generic checker: sqlj.online=sqlj.semantics.JdbcChecker ### Offline checker ### #sqlj.cache=on Page 40 40 Page 41 41