JaybirdからFirebirdへ接続する
Jaybirdとは
Jaybird は、Firebirdプロジェクトが開発しているタイプ4 jdbcドライバです。javaのデータベース接続用APIであるJDBCのうち、pure javaで書かれたモノがタイプ4となります。
これまでInterBase/Firebirdへの接続には、ボーランドが提供してきたInterClientが広く利用されてきましたが、こちらは中継サーバを利用するタイプ3となっています。
JaybirdとInterClientで最大の違いは何であるかを考えると、Jaybirdはインストールが不要であるという点だと思います。Jaybirdはfirebirdsql-full.jarに必要なクラスが一式含まれているので、これさえあればFirebirdのクライアント・ライブラリも中継サーバも不要です。
一方、リリースノート等によると、InterClientと比較して速くなっている部分もありますが、Insert系などで50%程遅くなっている部分もあります。得手不得手を理解して、使い分ける必要があるかもしれません。
本稿では、JayBirdに付属するサンプルコードの解説を通して、JayBirdの利用方法を示していきます。
(2004/5/23)
実行環境について
Jaybird の最新安定版は、1.0.1 となっています。ダウンロードは、SourceForgeのFirebirdプロジェクト・エリアまたは IBPhoenix社のサイトから行います。
- SourceForge.net
http://firebird.sourceforge.net/index.php?op=files&id=jaybird - IBPhoenix
http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_download_jaybird
ダウンロードしたFirebirdSQL-1.0.1.zipを解凍すると以下のファイルが出てきます。
faq.html FAQ.txt firebirdjmx.jar firebirdsql-full.jar firebirdsql-test.jar firebirdsql.jar firebirdsql.rar JDBC20_conformance.html release_notes.html <examples> DataSourceExample.java DriverExample.java <lib> jaas.jar log4j-core.jar mini-concurrent.j mini-j2ee.jar
サンプルコードを利用するためには、とりあえずfirebirdsql-full.jarがあれば事足ります。classpathを指定するのが面倒ですから、とりあえずサンプルコードと同じディレクトリに放り込んでおきます。
まずは、DriverExample.javaをコンパイルして実行してみます。
javaの実行環境は、java2SDK 1.4.2_04 on Windows2000を利用しています。
Firebirdは、Windows2000上にインストールされた、Firebird 1.0.3に接続しました。
ソースコード修正点
Jaybird に付属するサンプルコード DriverExample.javaを少しだけ変更してみました。
変更点:
引数によって、ドライバのロード方法を変更出来るようにした。
DriverExample.java
(28-29)
変更前
String user = "sysdba";
String password = "masterkey";
変更後:
String user = "sysdba";
try {
user = args[1];
}
catch (ArrayIndexOutOfBoundsException e) {
// At least an argument is needed. User is an option.
System.out.println("User is not appointed. 'sysdba' is used.");
System.out.println(e.getMessage());
}
String password = "masterkey";
try {
password = args[2];
}
catch (ArrayIndexOutOfBoundsException e) {
// At least an argument is needed. Password is an option.
System.out.println("Password is not appointed. 'masterkey' is used.");
System.out.println(e.getMessage());
}
(59)
変更前:
int registrationAlternative = 1;
変更後:
int registrationAlternative = 1;
try {
registrationAlternative = Integer.parseInt(args[0]);
}
catch (ArrayIndexOutOfBoundsException e) {
// At least an argument is needed
System.out.println("At least an argument is needed");
System.out.println(e.getMessage());
return;
}
catch (java.lang.NumberFormatException e) {
// The argument does not have the appropriate format
System.out.println("The argument must be a number format");
System.out.println(e.getMessage());
return;
}
実行結果
それでは、まずコンパイルしてみます。-classpath には Jaybirdの.jarファイルを指定します。
-deprecation オプションを付けてみましょう。
警告が出ています。runFinalizersOnExit()は推奨されていないということですが、サンプルコード中の解説は以下のようになっています。
もし、上記のように明示的にデータベース・オブジェクトをクローズしない場合、データベースオブジェクトはオブジェクトのファイナライザによってクローズされますが、ファイナライザがいつ実行されるのか、また、実行されるのかどうかさえも保証されていません。
一般に、オブジェクトのファイナライザは、プログラム終了時に実行されません。
JDBCオブジェクトについては、明示的にクローズすることが推奨されていますが、System.runFinalizersOnExit(true) を使う事もできます。ここでは、main()メソッドの先頭で記述しました。このようにすると、ファイナライザはプログラム終了時に強制的に実行されるようになります。
サンプルコード中では、Connection c を、最終的にクローズしているので、System.runFinalizersOnExit(true) は不要ですが、こういうやり方もあるということで記述されたのでしょう。
引数に1〜4までの数値を指定して、実行してみると、全て同じ結果を返すことがわかります。
jdbcドライバのロード
DriverExample.javaでは、4通りのjdbcドライバのロード方法を示しています。
-
Class.forName()を利用する
Class.forName ("org.firebirdsql.jdbc.FBDriver"); -
DriverManager.registerDriver()を利用する
java.sql.DriverManager.registerDriver ( (java.sql.Driver) Class.forName ("org.firebirdsql.jdbc.FBDriver").newInstance () -
システムの jdbc.drivers プロパティ・リストを利用する
java.util.Properties sysProps = System.getProperties (); StringBuffer drivers = new StringBuffer ("org.firebirdsql.jdbc.FBDriver"); String oldDrivers = sysProps.getProperty ("jdbc.drivers"); if (oldDrivers != null) drivers.append (":" + oldDrivers); sysProps.put ("jdbc.drivers", drivers.toString ()); System.setProperties (sysProps); -
jdbcドライバのインスタンスを直接生成する
d = new org.firebirdsql.jdbc.FBDriver ();
jdbcドライバの取得、バージョン情報
次に、DriverManager から、ドライバを取得しています。また、ここでドライバのバージョンを表示しています。
※納得いかないのが、バージョン 0.1になっていることです。
-
ドライバの取得、バージョン情報の表示
d = java.sql.DriverManager.getDriver (databaseURL); System.out.println ("Firebird JCA-JDBC driver version " + d.getMajorVersion () + "." + d.getMinorVersion () + " registered with driver manager.");
コネクションの取得
コネクションの取得についても、2通りの方法を示しています。
-
DriverManagerを利用してコネクションを取得する
c = java.sql.DriverManager.getConnection (databaseURL, user, password); -
システムのjdbc.drivers プロパティ・リストから直接取得する
java.util.Properties connectionProperties = new java.util.Properties (); connectionProperties.put ("user", user); connectionProperties.put ("password", password); c = d.connect (databaseURL, connectionProperties);
コネクションを通じた操作
ここから、jdbcドライバを通じてFirebirdを操作していきます。
-
AutoCommitをOFFにする
c.setAutoCommit (false); -
トランザクションのサポート状況を確認する
java.sql.DatabaseMetaData dbMetaData = c.getMetaData (); // Ok, let's query a driver/database capability if (dbMetaData.supportsTransactions ()) System.out.println ("Transactions are supported."); else System.out.println ("Transactions are not supported.");
-
ビューの一覧を取得する
// What are the views defined on this database? java.sql.ResultSet tables = dbMetaData.getTables (null, null, "%", new String[] {"VIEW"}); while (tables.next ()) { System.out.println (tables.getString ("TABLE_NAME") + " is a view."); } tables.close ();
-
UPDATE文を実行する
※このSQLはチェック制約に違反するので、失敗します// Let's try to submit some static SQL on the connection. // Note: This SQL should throw an exception on employee.gdb because // of an integrity constraint violation. try { s = c.createStatement (); s.executeUpdate ("update employee set salary = salary + 10000"); } catch (java.sql.SQLException e) { System.out.println ("Unable to increase everyone's salary."); showSQLException (e); // We expected this to fail, so don't return, let's keep going... } -
SELECT文を実行して、結果セットを取得する
// Let's submit some static SQL which produces a result set. // Notice that the statement s is reused with a new SQL string. try { rs = s.executeQuery ("select full_name from employee where salary < 50000"); } catch (java.sql.SQLException e) { System.out.println ("Unable to submit a static SQL query."); showSQLException (e); // We can't go much further without a result set, return... return; }
-
取得した結果セットから、列数と、フィールドタイプを取得する
// The query above could just as easily have been dynamic SQL, // eg. if the SQL had been entered as user input. // As a dynamic query, we'd need to query the result set meta data // for information about the result set's columns. try { java.sql.ResultSetMetaData rsMetaData = rs.getMetaData (); System.out.println ("The query executed has " + rsMetaData.getColumnCount () + " result columns."); System.out.println ("Here are the columns: "); for (int i = 1; i <= rsMetaData.getColumnCount (); i++) { System.out.println (rsMetaData.getColumnName (i) + " of type " + rsMetaData.getColumnTypeName (i)); } } catch (java.sql.SQLException e) { System.out.println ("Unable to extract result set meta data."); showSQLException (e); // What the heck, who needs meta data anyway ;-(, let's continue on... }
-
結果セットから値を取り出す
// Ok, lets step thru the results of the query... try { System.out.println ("Here are the employee's whose salary < $50,000"); while (rs.next ()) { System.out.println (rs.getString ("full_name")); } } catch (java.sql.SQLException e) { System.out.println ("Unable to step thru results of query"); showSQLException (e); return; }
後始末・・・
データーベースへの操作が終了したら、後始末を行います。
-
結果セットのクローズ、ステートメントのクローズ、コネクションのロールバック・クローズ
// This finally clause will be executed even if "return" was called in case of any exceptions above. finally { System.out.println ("Closing database resources and rolling back any changes we made to the database."); // Now that we're all finished, let's release database resources. try { if (rs!=null) rs.close (); } catch (java.sql.SQLException e) { showSQLException (e); } try { if (s!=null) s.close (); } catch (java.sql.SQLException e) { showSQLException (e); } // Before we close the connection, let's rollback any changes we may have made. try { if (c!=null) c.rollback (); } catch (java.sql.SQLException e) { showSQLException (e); } try { if (c!=null) c.close (); } catch (java.sql.SQLException e) { showSQLException (e); } }