Derby初心者のための自習チュートリアル(抜粋)
Apache Derby公式サイトで公開されているチュートリアルについて、とくに組み込み用途に関係する部分を抜粋して翻訳してみました。Java言語初心者でも分かるように説明されているのはちょっとやりすぎのような気もしますが、ともあれ自作プログラムに組み込んで使用するのに必要なベーシックな内容は含まれているかと思います。
原典のチュートリアルでは章・説が樹構造をとっていて直列化できないかたちになっていましたので、その点は翻訳掲載するにあたって若干修正(重複した内容のカット)が必要でした。それ以外はとくに変更はしていません。チュートリアルで学べることの概要については本文冒頭でも出てきますが、それらのうちで今回翻訳したのは、「アクティビティ1:組み込みドライバを使用してSQLを実行」と「アクティビティ3:組み込みドライバを使用してJDBCプログラムを実行」です。
チュートリアルの内容の理解のためには、公式サイトのダウンロード・ページから入手できる配布ファイル──つまりZIPファイルに含まれるデモ・プログラムのコードが手元にあったほうがよいと思います。
* * *
Derby初心者のための自習チュートリアル
Derbyについてできる限り早く理解し使用できるようになるよう、この自習ガイドではDerbyの機能/特徴のなかでも重要な部分に焦点を当てています。
チュートリアルの難易度とソフトウェア要件
このチュートリアルでは、組み込み型もしくはクライアント/サーバ型の設定環境下でDerbyを使用する方法を実演するために設計された一連のアクティビティ〔作業〕を行っていきます。これらのアクティビティをこなしていくことで、あなたはDerbyが容易に使用でき、しかも十分な機能を備えたリレーショナル・データベース管理システム(RDBMS)であることを理解できるでしょう。
チュートリアルのアクティビティを進めるにあたり、JavaソフトウェアやJavaデータベース・コネクティヴィティ(JDBC)APIそしてSQLについての予備知識は必要ありません。どの作業でも、あなたがそれぞれの手続きを行うために必要になるコマンドの完全な構文を提示しています。説明の中ではUNIXのKornシェルとWindowsコマンド・プロンプトの双方にための構文が紹介されています。
このチュートリアルではJavaプログラムやJDBC、SQLのコードを、教授/指導することによってではなく、それらを提示し実演することによって学習を助けるようにしています。それぞれのトピックについて、より深く理解したいのであれば、別の参考資料をあたってみる必要があるでしょう。
チュートリアルを進めるにあたり、次の物が必要になります:
システム設定
チュートリアルに入る前に、システム設定を確認してください。
チュートリアルについての問題とフィードバック
もしチュートリアルのなかで何かしらの問題に遭遇したなら、derby-user@db.apache.orgにE-mailを送って知らせてください。Derbyコミュニティの誰かしらがあなたのメッセージに応えてくれるはずです。
いただいた質問やフィードバックは、チュートリアルをよりよくするために利用させていただきます。
- チュートリアルの概観
自習チュートリアルに登場する作業はそれぞれDerbyの機能/特徴の重要な部分に焦点を当てています。 - アクティビティ1:組み込みドライバを使用してSQLを実行
このアクティビティでは、Derbyデータベース・エンジンを読み込み、データベースを作成し、そこに接続、いくつかの基本的なSQLステートメントを実行するために、組み込みドライバを使用します。 - アクティビティ2:クライアント・ドライバを使用してSQLを実行
このアクティビティでは、ネットワーク・サーバを使用し、クライアント/サーバ設定環境下でDerbyを使用します。ijツールはDerbyネットワーク・サーバに接続するクライアント・アプリケーション〔対話型のクライアント・プログラム〕です。アクティビティでは、seconddbという名前のデータベースを作成して、いくつかの基本的なSQLステートメントを実行しています。 - アクティビティ3:組み込みドライバを使用してJDBCプログラムを実行
このアクティビティではシンプルなJava JDBC〔クライアント〕プログラムを使用してDerbyデータベース・エンジンを読み込んでいます。 - アクティビティ4:クライアント・ドライバとネットワーク・サーバを使用してJDBCプログラムを作成・実行
このアクティビティでは、Derbyを組み込みで使用するプログラムを、Derbyネットワーク・サーバを用いてクライアント/サーバ型で動作する実装に変更するのがいかに容易であるかをご覧に入れます。 - Derbyについてもっと知るには?
おめでとうございます。すべてのアクティビティを終了しました。今やあなたは、組み込み型とクライアント/サーバ型の両方でDerbyを使用する方法を学び終えました。
〔訳注:繰り返しになりますが、今回抜粋翻訳をおこなったのはアクティビティ1と3のみです。〕
アクティビティ1:組み込みドライバを使用してSQLを実行
このアクティビティでは、Derbyデータベース・エンジンを読み込み、データベースを作成してそこに接続、基本的なSQLを実行するのに組み込みドライバを使用してみます。
ディレクトリを作成し、スクリプトをコピーする
このアクティビティを行うにあたって、まずはディレクトリを作成して、そこにいくつかのSQLスクリプトをコピーする必要があります。これらのスクリプトは、これから作成するDerbyデータベースに対して速やかにテーブルとデータを登録するために使用します。
ヒント:それぞれのコマンドを実行したあとでコマンド・プロンプトが表示されるはずです。もしエラーが起きたら、実行したコマンドの構文を確かめて再入力してください。
- コマンド入力画面〔コマンド・プロンプトやシェルの画面〕を開き、自習チュートリアルのアクティビティのため作成したファイルを格納するディレクトリに移動します。
- 次に示すにしてDERBYTUTORディレクトリを作成します。DERBYTUTORはこのアクティビティを通じてあなたが作業を行うディレクトリになります。
OS コマンド UNIX (Korn Shell) mkdir DERBYTUTOR Windows md DERBYTUTOR - DERBYTUTORに移動します。
OS コマンド UNIX (Korn Shell) cd DERBYTUTOR Windows cd DERBYTUTOR - demo\programs\toursdb ディレクトリの中に格納されたSQLスクリプトを、DERBYTUTORにコピーします。これらのスクリプトは後ほど、新規作成するtoursdbデータベースにテーブルとデータを登録するのに使います。
OS コマンド UNIX (Korn Shell) cp $DERBY_HOME/demo/programs/toursdb/*.sql . Windows copy %DERBY_HOME%\demo\programs\toursdb\*.sql . 〔訳注:以降の解説のなかで登場する環境変数$DERBY_HOMEは、チュートリアルの別の箇所で設定されているもので、実際上は公式サイトからダウンロードした配布ファイル、つまりZIPファイル(例えばdb-derby-10.10.1.1-bin.zip)を展開したディレクトリを単に指しているだけです。前述の解説ではまた、環境変数$PATHに$DERBY_HOME/binを追加する作業も行っています。したがって以降の解説は、binディレクトリ配下のijツールなどがパス指定なしで使用可能である前提で進みます。〕
- DERBYTUTORディレクトリにファイルがコピーできていることを確認しましょう。
Derbyデータベースを作成しSQLステートメントを実行する
さて、Derby ijツールでDerbyデータベース・エンジンを読み込んでみましょう。新規にfirstdbデータベースを作成するためにDerby組み込みドライバを使用します。またこうして作成したデータベースにテーブルを作成しデータを投入するために、いくつかの基本的なSQLステートメントを実行することになります。
- Derby ijツールを起動します。$DERBY_HOME/binが環境変数$PATHに含まれている場合、次のようにタイプするだけです:ij
あるいは次のようにしてJavaコマンドでijツールを起動することもできます。
OS コマンド UNIX (Korn Shell) java -jar $DERBY_HOME/lib/derbyrun.jar ij ij version 10.10 Windows java -jar %DERBY_HOME%\lib\derbyrun.jar ij ij version 10.10 - 組み込みドライバを使用してデータベースを作成し、接続をオープンします。
CONNECT 'jdbc:derby:firstdb;create=true';
接続コマンドの説明:
- connect
- このijコマンドでデータベースへの接続を確立します。Derby接続URLはシングル・クオテーションで囲います。ijコマンドは大文字でも小文字でも構いません。
- jdbc:derby:
- DerbyドライバのためのJDBCプロトコルを指定しています。
- firstdb
- データベース名です。名前にはいかなる文字列も使用可能です。ファイルパスが指定されていないため、データベースはデフォルトで作業ディレクトリ(DERBYTUTOR)に作成されます。
- ;create=true
- このDerby URL属性はデータベースを作成するために使用します。Derbyはcreate databaseコマンドを持ちません。〔訳注:したがってDBインスタンスを新規に作成する場合、この接続文字列の属性指定を用いることになります。〕
- ;(セミコロン)
- このセミコロンはijコマンドの終端を示すものです。
- 標準のSQLを使って、2つのカラムを持つテーブルをつくります。
CREATE TABLE FIRSTTABLE (ID INT PRIMARY KEY, NAME VARCHAR(12)); 0 rows inserted/updated/deleted
- 3レコードをINSERTします。
INSERT INTO FIRSTTABLE VALUES (10,'TEN'),(20,'TWENTY'),(30,'THIRTY'); 3 rows inserted/updated/deleted
- テーブルからすべてのレコードをSELECTします。
SELECT * FROM FIRSTTABLE; ID |NAME ------------------------ 10 |TEN 20 |TWENTY 30 |THIRTY 3 rows selected
- IDが20であるものに限定したSELECTを行ってみます。
SELECT * FROM FIRSTTABLE WHERE ID=20; ID |NAME ------------------------ 20 |TWENTY 1 row selected
- 任意:さらにいくつかテーブルとその他のスキーマ・オブジェクトを作成して、データを投入してみましょう。
- SQLスクリプト ToursDB_schema.sql を読み込んでみます。
run 'ToursDB_schema.sql'; ij> ... CREATE TABLE AIRLINES ( AIRLINE CHAR(2) NOT NULL , AIRLINE_FULL VARCHAR(24), BASIC_RATE DOUBLE PRECISION, ... 0 rows inserted/updated/deleted ...その他のメッセージが続く ...
- 続いてSQLスクリプトloadTables.sql を実行してテーブルにデータを投入します。
run 'loadTables.sql'; ij> run 'loadCOUNTRIES.sql'; ij> insert into COUNTRIES values ( 'Afghanistan','AF','Asia'); 1 row inserted/updated/deleted ij> insert into COUNTRIES values ( 'Albania','AL','Europe'); 1 row inserted/updated/deleted ... その他のメッセージが続く ...
- SQLスクリプト ToursDB_schema.sql を読み込んでみます。
- ijツールを終了します。
exit;
これでDERBYTUTORディレクトリに戻ります。
- このアクティビティで作成されたもっとも重要なファイル群について見ていきましょう。
アクティビティ3:組み込みドライバを使用してJDBCプログラムを実行
このアクティビティではシンプルなJDBCクライアント・プログラムからDerbyデータベース・エンジンを読み込む方法を学びます。
このアクティビティではあなたがすでにコマンド画面を開いており、DERBYTUTORディレクトリに移動しているということを前提にしています。
JDBCは〔汎用の〕Javaデータベース・コネクティビティAPIの略であり、Derbyを操作するためのネイティブAPIでもあります。プログラムはjdbcDemoDBデータベースを(もし存在しなければ)作成してそこに接続するために、組み込みドライバを使用しています。〔このプログラムによって〕あなたはデータベースのテーブルにテキスト入力したデータを投入していくことができます。プログラムは基本的なJDBC処理とそれにつきもののエラー処理とについて実例を示す物です。
Javaコンパイラと実行環境は、Derbyとその他のJavaアプリケーションを実行するのに必要になるバイナリファイル群(JARファイルやクラス・ファイル)を探すのに、CLASSPATH環境変数により指定されたクラスパスを使用します。このアクティビティを行う前に、クラスパスの設定と、WwdEmbedded.javaプログラム〔アクティビティのなかではこのプログラムのクラス・ファイルがクラスパス上にあることを前提にしている〕のコンパイルとを済ませておく必要があります。
- プログラム・ファイル群をDERBYTUTORディレクトリにコピーし、CLASSPATH環境変数を設定します。
OS コマンド UNIX (Korn Shell) cp $DERBY_HOME/demo/programs/workingwithderby/* . export CLASSPATH=$DERBY_HOME/lib/derby.jar:. |
Windows copy %DERBY_HOME%\demo\programs\workingwithderby\* . set CLASSPATH=%DERBY_HOME%\lib\derby.jar;. |
重要:各コマンドの末尾のドット(.)を忘れないこと。これによりあなたのカレント・ディレクトリがクラスパスに含まれるようになり、またカレント・ディレクトリにファイル群がコピーされます。 - プログラム・ソースコードをコンパイルします。サンプル・プログラムはWwdEmbedded.java と WwdUtils.java の2つのソースコード・ファイルに含まれています。次のコマンドを実行して2つを同時にコンパイルしてしまいます:
javac WwdEmbedded.java WwdUtils.java
重要:コンパイルが成功したらコマンド・プロンプトが表示されます。そしてバイナリ・ファイルとしてWwdEmbedded.class と WwdUtils.classが作成されます。エラー・メッセージが表示されたら、JDKがきちんとインストールされているか確認してください。
- プログラムを実行します。WwdEmbedded.javaプログラムはウィッシュリスト〔wish-list〕のアイテムをテーブルに登録します。このプログラムはあなたにテキストの入力(最大で32文字)を求め、入力されたテキストをデータベースに登録します。その後テーブルに登録されているアイテムを一覧表示します。プログラムはあなたがexitと入力するか何かしら思いがけない問題が発生するかするまでウィッシュリストのアイテムについて質問を続けます。いくつかの基本的情報は、プログラムの開始と終了のときに画面に表示されます。
java WwdEmbedded org.apache.derby.jdbc.EmbeddedDriver loaded. Connected to database jdbcDemoDB . . . . creating table WISH_LIST Enter wish-list item (enter exit to end): a peppermint stick __________________________________________________ On 2012-09-14 09:46:37.77 I wished for a peppermint stick __________________________________________________ Enter wish-list item (enter exit to end): a long vacation __________________________________________________ On 2012-09-14 09:46:37.77 I wished for a peppermint stick On 2012-09-14 09:46:51.654 I wished for a long vacation __________________________________________________ Enter wish-list item (enter exit to end): exit Closed connection Database shut down normally Getting Started With Derby JDBC program ending.
WwdEmbeddedプログラム
この節ではWwdEmbedded.javaについて、JDBCクライアント・プログラムからDerbyデータベースにアクセスする方法の詳細に焦点をあてながら解説していきます。
アクティビティで実行するデータベースに関連するほとんどのコードはこのセクションの中に登場します。しかしプログラム・ファイルをテキスト・ビューワやエディタで開いて内容を見ていくことで理解の助けとなるでしょう。〔以降の本文中、大文字で示した〕SECTIONの名前はプログラム・コードのコメントの中にも記載されているので、チュートリアルの説明とプログラムとを相互に参照するのに役立つはずです。プログラムはWwdUtilsクラスのメソッドを使用しています。このユーティリティ・クラスのコードについてはここでは解説しませんが、WwdUtils.javaファイルを参照することで理解することができます。
プログラムの起動
INITIALIZATION SECTION:最初の数行はプログラムが使用しているJavaパッケージの指定と、JavaクラスWwdEmbeddedの宣言とmainメソッド・シグネチャからなります。
import java.sql.*; public class WwdEmbedded { public static void main(String[] args) {
重要な変数とオブジェクトの定義
DEFINE VARIABLES SECTION: mainメソッドの最初の数行では、プログラムが使用する変数とオブジェクトが定義されています。この例ではDerbyデータベースに接続するのに必要な情報を格納するために変数を使用しています。こうして情報を格納する変数を使用することで、プログラムをその他の設定、その他のデータベースに適合させるのが簡単になります。
- driver
- Derby組み込みドライバの名前を格納します。
- dbName
- データベース名を格納します。
- connectionURL
- データベースにアクセスするのに使用されるDerby接続URLを格納します。
- createString
- WISH_LISTテーブルのためのSQL CREATEステートメントを格納します。
String driver = "org.apache.derby.jdbc.EmbeddedDriver"; String dbName="jdbcDemoDB"; String connectionURL = "jdbc:derby:" + dbName + ";create=true"; ... String createString = "CREATE TABLE WISH_LIST " + "(WISH_ID INT NOT NULL GENERATED ALWAYS AS IDENTITY " ... + " WISH_ITEM VARCHAR(32) NOT NULL) " ;
Derbyエンジンの起動
LOAD DRIVER SECTION: Derby組み込みJDBCドライバをロードすることでDerbyデータベース・エンジンが起動します。try…catchブロック(Javaのエラー処理構文)は例外が発生した場合にこれをとらえます。この段階で発生する問題は正しいクラスパス設定ができていないことに起因するものであることが多いです。
String driver = "org.apache.derby.jdbc.EmbeddedDriver"; ... try { Class.forName(driver); } catch(java.lang.ClassNotFoundException e) { ... }
データベースを起動
BOOT DATABASE SECTION: DriverManagerはconnectionURL変数に格納されたDerby接続URLを使用してデータベースを読み込みます。このURLはパラメータとして;create=trueを含んでいます。これによってデータベースがまだ存在しない場合、それが〔自動で〕作成されるようになります。最初のtry...catchブロックがここから始まります。データベースにアクセスするコードでエラーが発生した場合、この文で処理されます。
String connectionURL = "jdbc:derby:" + dbName + ";create=true"; ... try { conn = DriverManager.getConnection(connectionURL); ... <most of the program code is contained here> } catch (Throwable e) { ... }
SQLを実行するためのプログラムを準備
INITIAL SQL SECTION:続くSQLの操作を実行するために必要なオブジェクトを初期化します。そして必要なデータ・テーブルが存在するかどうか検証します。
ここでステートメント・オブジェクト〔Statementインターフェース実装のインスタンス〕であるsが初期化されます。ユーティリティ・メソッドWwdUtils.wwdChk4TableによりWISH_LISTテーブルが存在しないとわかったら、ステートメント・オブジェクトのexecuteメソッドにより、createString変数に格納されたSQLが実行され、当該テーブルが作成されます。
s = conn.createStatement(); if (! WwdUtils.wwdChk4Table(conn)) { System.out.println (" . . . . creating table WISH_LIST"); s.execute(createString); }
テーブルにデータを追加するためのINSERTステートメントには、プリペアード・ステートメント・オブジェクトpsInsertを使用します。プリペアード・ステートメントにはパラメータとしてクエスチョン・マーク(?)を使用します。これはユーザにより挿入される実際のデータの代わりになります。実際の値はもっとあと、SQLを実行する前に設定されます。このプリペアード・ステートメントを使う方法は、何度も使用されるSQLステートメントを実行するときに効率的です。
psInsert = conn.prepareStatement
("insert into WISH_LIST(WISH_ITEM) values (?)");
データベースとのやり取り
ADD / DISPLAY RECORD SECTION:このセクションではユーティリティ・メソッドWwdUtils.getWishItemを使ってユーザから情報を収集しています。WISH_LISTテーブルにデータを登録するのにはあらかじめ用意しておいた〔プリペアード・ステートメントの〕オブジェクトを使用します。そしてすべてのレコードを画面に表示します。doループにより、一連の手続きはユーザがexitと入力するまで繰り返されます。このセクションで実行されるデータに関連する操作は次の通りです:
- setStringメソッドによりpsInsertオブジェクトの置換パラメータは、ユーザが入力した値に置き換えられます。そしてexecuteUpdateメソッドによりデータベースへのデータ挿入が実施されます。
psInsert.setString(1,answer); psInsert.executeUpdate();
- ステートメント・オブジェクトsはWISH_LISTテーブルからすべてのレコードを抽出し、それらをResultSetオブジェクトであるmyWishesに格納するために使用されます。
myWishes = s.executeQuery("select ENTRY_DATE, WISH_ITEM from WISH_LIST order by ENTRY_DATE");
whileループは都度nextメソッドをコールすることでレコードを1行1行読み取っていきます。getTimestamp と getStringメソッドはレコードからそれぞれ指定されたフィールドの値を取得して適切な型で返します。それらの値はデフォルトのフォーマットで文字列化されて画面に表示されます。
while (myWishes.next()) { System.out.println("On " + myWishes.getTimestamp(1) + " I wished for " + myWishes.getString(2)); }
メモリを解放するためResultSetオブジェクトをクローズします。
myWishes.close();
データベースのシャットダウン
DATABASE SHUTDOWN SECTION:アプリケーションがDerbyエンジンを始動させたら、アプリケーションが終了する前にすべてのデータベースをシャットダウンしなくてはなりません。Derby接続URLに;shutdown=true属性を含めることでこのシャットダウンを実施するようになります。Derbyエンジンをシャットダウンするとき、起動していたデータベースはすべて自動的にシャットダウンされるのです。シャットダウンの過程では、次回のデータベース起動がすみやかに実施できるように、トランザクション・ログに記録のあるレコードが整理されます。
ヒント:接続URLにデータベース名を含めることで、〔上述の〕Derbyエンジンのシャットダウンと関わりなくデータベースだけを個別にシャットダウンすることもできます。
このセクションでは、〔まず〕組み込みドライバが使用されていることを確認の上で、シャットダウン・コマンドを発行し、シャットダウン例外をキャッチ、Derbyエンジンがきちんとシャットダウンされたことを確認します。
if (driver.equals("org.apache.derby.jdbc.EmbeddedDriver")) { boolean gotSQLExc = false; try { DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException se) { if ( se.getSQLState().equals("XJ015") ) { gotSQLExc = true; } } if (!gotSQLExc) { System.out.println("データベースは正常に終了なかった"); } else { System.out.println("データベースは正常に終了した"); } }
重要:エラーXJ015(Derbyエンジンが成功裏にシャットダウンしたことを示す)と08006エラー(1つのデータベースが成功裏にシャットダウンしたことを示す)は、処理が成功をしたことを示すためにDerbyがスローする唯一の例外で、その他のすべての例外は処理の失敗を示すものです。〔したがってこれらの例外が発生した場合は〕内容を確かめるためにログ・ファイルをチェックする必要があります。
errorPrintメソッドと SQLExceptionPrint メソッド
DERBY EXCEPTION REPORTING CLASSES:ファイルの終わりの方に、2つのメソッド──errorPrintメソッドと SQLExceptionPrint メソッドがあります。これらはどんなJDBCクライアント・プログラムであっても使用できる一般的な例外報告用メソッドです。しばしば複数の例外(SQLException)が連鎖して発生しそれらが一括してスローされてくるため、例外型のハンドリングは必須です。whileループは一連のエラーをひとつずつ報告するために使用されています。データベースにアクセスするそれぞれのコードに配されたcatchブロックからerrorPrintメソッドが呼び出されることでこの処理過程が開始されます。
// Beginning of the primary catch block: uses errorPrint method } catch (Throwable e) { /* Catch all exceptions and pass them to ** the exception reporting method */ System.out.println(" . . . exception thrown:"); errorPrint(e); }
errorPrintメソッドはSQLException〔とそのサブクラス〕を除くすべての例外についてスタックトレースを出力します。SQLException〔のサブクラス〕のそれぞれについてはSQLExceptionPrintメソッドに渡します。
static void errorPrint(Throwable e) { if (e instanceof SQLException) SQLExceptionPrint((SQLException)e); else { System.out.println("A non SQL error occured."); e.printStackTrace(); } } // END errorPrint
SQLExceptionPrintメソッドは積み重なった一つひとつの例外について繰り返し処理を実施します。それぞれのエラーについて、エラーコード、エラーメッセージ、そしてスタックトレースを画面に表示します。
// Iterates through a stack of SQLExceptions static void SQLExceptionPrint(SQLException sqle) { while (sqle != null) { System.out.println("\n---SQLException Caught---\n"); System.out.println("SQLState: " + (sqle).getSQLState()); System.out.println("Severity: " + (sqle).getErrorCode()); System.out.println("Message: " + (sqle).getMessage()); sqle.printStackTrace(); sqle = sqle.getNextException(); } } // END SQLExceptionPrint
このメソッドが生成する出力を確認してみたければ、ウィッシュリストのアイテムとして32文字以上のテキスト──“I wish to see a Java program fail”(Javaプログラムが落ちるのを見てみたい)とか──を入力してみてください。
* * *
このドキュメントは翻訳物です。原典は、Apache Derby公式サイトで公開されているチュートリアルです。