JavaDBは、Apache Derbyというデータベースを
Oracleがサポートすることでjava標準でJDK1.6以降に追加されました。
なんですが、今回(2019年4月現在)サンプルを作成しようとしたところ、
derbyのライブラリが見当たらない・・・・。
どうやらこちらをみると最近は同梱されなくなったみたいですね・・・。
※情報ありがとうございます!
java標準なので!ということで採用するという力技は難しくなっちゃいました笑
本来は[jdk_home]/db/ibの配下にderby.jarが同梱されています。
※今僕が使用しているpleiades(eclipse ver4.10.0)では、javaは
6、7、8、11と入っていますが実際derby.jarが同梱されているのは、
7のみでした。
ただ、実際にプロジェクトなんかで使用する時は、
javaの標準ではクラスパス通ってないので、
結局mavenのリポジトリ参照するということが必要になります。
同梱されているだけでは、そのまま使えませんよという感じです。
なので、同梱されなくなりましたというのも
わからない話ではないかなといった印象ですが・・・。
さて、ここからが本題。
derbyはもちろん永続化されたDBとしても利用できますが、
インメモリで使用することができます。
おそらくそのあたりを狙ってか、
mavenのセントラルリポジトリでpomを確認すると、
scopeはtestになってますね。
jenkinsなどのCI利用を考えると、
永続化DBに接続はさせられないので、
インメモリで使用させたいってことなのでしょうか??
では、実際にその使用方法について書いていきたいと思います。
今回はmavenプロジェクトで実施します。
derby事前準備
今回は同梱されたderby.jarではなく、
mavenセントラルリポジトリから参照することにします。
pomに以下のように依存関係を追加します。
準備はこれだけです。
<dependency> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> <version>10.14.2.0</version> </dependency>
※2019年4月現在、最新のversionは10.15.1.3なのですが、
これを依存関係に追加してしまうと、以下のExceptionによりうまく動作しません。
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/derby/shared/common/security/SystemPermission at org.apache.derby.iapi.jdbc.AutoloadedDriver.connect(AutoloadedDriver.java:134) at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677) at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251) at jp.co.tarchan.derbysample.DerbySample.main(DerbySample.java:16) Caused by: java.lang.ClassNotFoundException: org.apache.derby.shared.common.security.SystemPermission at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ... 4 more
ClassNotFoundなのですが、jarの中には確かに指定されたclassが無いので、
バグなのかしら?と思っております。
なので、今回はその1つ前のversionである10.14.2.0を使用することにしました。
使用サンプル
まずはサンプルコードを。
package jp.co.tarchan.derbysample; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; /** * Derby接続サンプル. */ public class DerbySample { /** * 主処理. * @param args 実行引数 */ public static void main(String[] args) { // インメモリとして使用するDerbyのDBを作成する try (Connection conn = DriverManager.getConnection("jdbc:derby:memory:TestDB;create=true"); Statement stmt = conn.createStatement();) { // テーブルをcreateする StringBuilder sb = new StringBuilder(); sb.append("CREATE TABLE TEST_USER ("); sb.append(" USER_ID VARCHAR(10) PRIMARY KEY,"); sb.append(" USER_NAME VARCHAR(50))"); stmt.executeUpdate(sb.toString()); // データを1件insert sb = new StringBuilder(); sb.append("INSERT INTO TEST_USER ("); sb.append(" USER_ID,"); sb.append(" USER_NAME"); sb.append(") VALUES ("); sb.append(" 'ABC1234567',"); sb.append(" 'テスト太郎')"); stmt.executeUpdate(sb.toString()); // データをselect sb = new StringBuilder(); sb.append("SELECT * FROM TEST_USER"); ResultSet rs = stmt.executeQuery(sb.toString()); while (rs.next()) { System.out.println(rs.getString("USER_ID")); System.out.println(rs.getString("USER_NAME")); } } catch (Exception e) { e.printStackTrace(); } } }
解説
Connection作成のときのURL(jdbc:derby:memory:TestDB;create=true)これで
メモリ上にTestDBというDBが作成されます。
この時、create=trueとすることで、存在しなければ作成という挙動になります。
接続が確立された後は、通常のjdbcを使用した接続と大きく変わることは
ありません。
テーブル作成の時のカラム型はこちら。
おまけ(インメモリ使用しない場合)
今回はderbyをインメモリで使用するサンプルについて
お話しましたが、では永続的なDBとして使用する場合はどうするのか?
というのをおまけとしてお話したいと思います。
記述の違いはjdbcURLのみ
永続的に使用する場合のインメモリとの違いはjdbcのURLのみで可能です。
記述の違いは以下です。
jdbc:derby:memory:TestDB;create=true
→
jdbc:derby:C:/test/TestDB;create=true
ここで注意することがあります。
指定するフォルダは中身のあるフォルダではいけません
また、存在してもいけません。
あくまで最後のTestDBはDB名なので、
事前にそのフォルダが存在すると、エラーとなります。
動作確認
永続化するということは、2度テーブル作成したりできないということになりますね。
ということで同じプログラムを2度実施してみました。
するとこんなエラーになります。
java.sql.SQLException: Table/View 'TEST_USER' already exists in Schema 'APP'. at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source) at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source) at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source) at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source) at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source) at org.apache.derby.impl.jdbc.ConnectionChild.handleException(Unknown Source) at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(Unknown Source) at org.apache.derby.impl.jdbc.EmbedStatement.execute(Unknown Source) at org.apache.derby.impl.jdbc.EmbedStatement.executeLargeUpdate(Unknown Source) at org.apache.derby.impl.jdbc.EmbedStatement.executeUpdate(Unknown Source) at jp.co.tarchan.derbysample.DerbySample.main(DerbySample.java:29) Caused by: ERROR X0Y32: Table/View 'TEST_USER' already exists in Schema 'APP'. at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) at org.apache.derby.impl.sql.catalog.DataDictionaryImpl.duplicateDescriptorException(Unknown Source) at org.apache.derby.impl.sql.catalog.DataDictionaryImpl.addDescriptor(Unknown Source) at org.apache.derby.impl.sql.execute.CreateTableConstantAction.executeConstantAction(Unknown Source) at org.apache.derby.impl.sql.execute.MiscResultSet.open(Unknown Source) at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(Unknown Source) at org.apache.derby.impl.sql.GenericPreparedStatement.execute(Unknown Source) ... 5 more
APPというスキーマにはTEST_USERというテーブルはすでに存在していますよ。となっていますね。想定通りですね。
ちなみに、今回のサンプルではユーザ・パス・スキーマすべてデフォルトになるので、
その場合はderbyではAPPというスキーマ、APPというユーザ、APPというパスワードとなります。
次回はderbyとjpaを組み合わせてテストを実施することについて
お話したいと思います。
それでは!
20代前半までは東京で音楽をやりながら両手の指以上の業種でアルバイト生活をしていましたが、某大手プロバイダのテレアポのバイトでPCの知識の無さに愕然とし、コンピュータをもっと知りたい!と思ったことをきっかけに25歳の時にITの世界に未経験で飛び込みました。
紆余曲折を経て、現在は個人事業主としてお仕事させていただいており、10年ほどになります。
web制作から企業システム構築、ツール開発など、フロントエンドもバックエンドもサーバーもDBAも依頼があれば何でもやってきた雑食系エンジニアです。
今風にいうとフルスタックエンジニアということになるのでしょうか??
→ 詳細プロフィールというか、生い立ちはこちら
→スキルシートをご覧になる場合はこちら
→お仕事のご依頼やお見積りなどお問い合わせはこちらから!