Apache Derby(或いは "Cloudscape")という RDB をご存知でしょうか?
最近は SQLite や HTML5 のローカルデータストアの台頭であまり名前を聞かなくなりましたが、Pure Java で記述された軽量の RDB です。元々は Cloudscape Inc. によって開発されましたが、Informix Software を経て IBM 製品として扱われていた時代もあります。その影響もあってか "DB2 互換 SQL" に対応し、DB2 の SQL が動く軽量の Java RDB という立ち位置でした。軽量であるが故に組み込み系のアプリケーション内で使われることが多いようです。歴史的には 2004 年に IBM から Apache 財団へソースコードが寄贈され、現在の Apache Derby という名称のプロジェクトになりました。また Oracle JDK 1.6 以降に(オプションとして)組み込まれている JavaDB の実装はこの Apache Derby です。
私自身は "Cloudscape" と呼ばれていた頃に使ったことがありました。今回、久しぶりに Apache Derby を使ってみました。
JDK のオプションに組み込まれているとはいえ、せっかくなので最新版を使ってみることにしました。まずは Apache Derby のダウンロードページから最新バージョン(2016/Oct/07 時点では 10.12.1.1)のリンクをクリックします:
最新版のアーカイブファイル:db-derby-(バージョン番号)-bin.zip をクリックしてダウンロードします:
ダウンロードした zip ファイルを展開し、lib フォルダ内の必要な JAR ファイルを取り出します。今回は本体である derby.jar と、日本語ロケールが含まれた derbyLocale_ja_JP.jar の2ファイルを取り出します:
この2ファイルを Java の開発環境から使えるようにします。J2SE/EE プロジェクトであれば、WebContent/WEB-INF/lib 以下にコピーするなどして、コンパイル/実行時に参照できるようにしておきます:
試しに以下のような index.jsp ファイルを用意してみました:
コードそのものは一般的な JDBC プログラミングです。DB を開く際に目的の DB が存在していない場合はその場で作成するようなオプション("create=true")を付与しています。また items というテーブルのレコード数を取得して、エラーが出るようであればテーブルが存在していないと判断し、新規に items テーブルを定義して作成し、2つほどデータを insert するようにしています。 最終的には items テーブル内の全レコードを画面に出力する、という内容にしています。
このプロジェクトを実行して、index.jsp にブラウザでアクセスすると以下のような表形式で2つのレコード内容が確認できます:
まあ普通に RDB として使うこともできますが、組み込み系以外であればフットプリントの小ささからローカルレプリカ DB として利用する、というケースも考えられます。特にサーバー側が DB2 だったりすると SQL 互換が便利に使えたりしますね。
久しぶりに Cloudscape を使ってみました。相変わらずですが( Java が動いている前提はありますが)JAR ファイル置くだけで使える RDB は便利ですね。
最近は SQLite や HTML5 のローカルデータストアの台頭であまり名前を聞かなくなりましたが、Pure Java で記述された軽量の RDB です。元々は Cloudscape Inc. によって開発されましたが、Informix Software を経て IBM 製品として扱われていた時代もあります。その影響もあってか "DB2 互換 SQL" に対応し、DB2 の SQL が動く軽量の Java RDB という立ち位置でした。軽量であるが故に組み込み系のアプリケーション内で使われることが多いようです。歴史的には 2004 年に IBM から Apache 財団へソースコードが寄贈され、現在の Apache Derby という名称のプロジェクトになりました。また Oracle JDK 1.6 以降に(オプションとして)組み込まれている JavaDB の実装はこの Apache Derby です。
私自身は "Cloudscape" と呼ばれていた頃に使ったことがありました。今回、久しぶりに Apache Derby を使ってみました。
JDK のオプションに組み込まれているとはいえ、せっかくなので最新版を使ってみることにしました。まずは Apache Derby のダウンロードページから最新バージョン(2016/Oct/07 時点では 10.12.1.1)のリンクをクリックします:
最新版のアーカイブファイル:db-derby-(バージョン番号)-bin.zip をクリックしてダウンロードします:
ダウンロードした zip ファイルを展開し、lib フォルダ内の必要な JAR ファイルを取り出します。今回は本体である derby.jar と、日本語ロケールが含まれた derbyLocale_ja_JP.jar の2ファイルを取り出します:
この2ファイルを Java の開発環境から使えるようにします。J2SE/EE プロジェクトであれば、WebContent/WEB-INF/lib 以下にコピーするなどして、コンパイル/実行時に参照できるようにしておきます:
試しに以下のような index.jsp ファイルを用意してみました:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.util.*" %> <%@ page import="java.io.*" %> <%@ page import="java.sql.*" %> <%@ page import="me.juge.derby.*" %> <% request.setCharacterEncoding("utf-8"); %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"> <head> <title>Derby JDBC Sample</title> </head> <body> <table border="1"> <tr><th>ID</th><th>NAME</th><th>PRICE</th></tr> <% final String driverName = org.apache.derby.jdbc.EmbeddedDriver.class.getCanonicalName(); final String dbName = "derbydb"; final String connURL = "jdbc:derby:" + dbName + ";create=true"; //. DBが存在していない場合は作成するオプション try{ Class.forName( driverName ); Connection conn = null; try{ conn = DriverManager.getConnection( connURL ); }catch( Exception e ){ } if( conn != null ){ ResultSet rs = null; //. 初期化 try{ //. 試しに items テーブルにアクセス Statement s0 = conn.createStatement(); rs = s0.executeQuery( "select count(*) from items" ); }catch( SQLException e ){ //e.printStackTrace(); String state = e.getSQLState(); if( state.equals( "42X05" ) ){ //. テーブルが存在しない try{ Statement s1 = conn.createStatement(); s1.execute( "create table items(" + " id int generated always as identity primary key" //. この辺りが DB2 互換 SQL + ", name varchar(100)" + ", price int" + " )"); PreparedStatement s2 = conn.prepareStatement( "insert into items( name, price ) values( ?, ? )" ); s2.setString( 1, "シャンプー" ); s2.setInt( 2, 1000 ); s2.execute(); PreparedStatement s3 = conn.prepareStatement( "insert into items( name, price ) values( ?, ? )" ); s3.setString( 1, "石鹸" ); s3.setInt( 2, 500 ); s3.execute(); }catch( Exception e1 ){ } }else if( state.equals( "42X14" ) || state.equals( "42821" ) ){ //. テーブル定義が不正 }else{ //. その他の想定外の例外 } }finally{ if( rs != null ) rs.close(); } //. レコード表示 try{ rs = conn.createStatement().executeQuery( "select * from items" ); while( rs.next() ){ int id = rs.getInt( 1 ); String name = rs.getString( 2 ); int price = rs.getInt( 3 ); %> <tr><td><%= id %></td><td><%= name %></td><td><%= price %></td></tr> <% } }catch( SQLException e ){ }finally{ if( rs != null ) rs.close(); } } }catch( Exception e ){ e.printStackTrace(); } %> </table> </body> </html>
コードそのものは一般的な JDBC プログラミングです。DB を開く際に目的の DB が存在していない場合はその場で作成するようなオプション("create=true")を付与しています。また items というテーブルのレコード数を取得して、エラーが出るようであればテーブルが存在していないと判断し、新規に items テーブルを定義して作成し、2つほどデータを insert するようにしています。 最終的には items テーブル内の全レコードを画面に出力する、という内容にしています。
このプロジェクトを実行して、index.jsp にブラウザでアクセスすると以下のような表形式で2つのレコード内容が確認できます:
まあ普通に RDB として使うこともできますが、組み込み系以外であればフットプリントの小ささからローカルレプリカ DB として利用する、というケースも考えられます。特にサーバー側が DB2 だったりすると SQL 互換が便利に使えたりしますね。
久しぶりに Cloudscape を使ってみました。相変わらずですが( Java が動いている前提はありますが)JAR ファイル置くだけで使える RDB は便利ですね。
コメント