Java

SpringBootとJavaDB(Derby)を連携させる

2019年1月21日

このページに書いてあること。

JavaFrameWorkのSpringBootとJDKにバンドルされており面倒な手続きなしで構築できるJavaDB(Derby)を連携させるのが思いのほか面倒だったのでメモ

  • JavaDBをインストールして、起動する(起動方法に違いあり)
  • Springからアクセスする

先ずはJavaDBをインストールしますが、こちらは公式サイトにあるbinのzipをダウンロードするだけなので省略します。

データの投入

インストール後、テストデータを投入します。

こちらの情報を使用させていただきました。ファイル名のみ、私の環境でのルールに合わせて変更しています。(テストデータ投入までは同じ内容ですが、こちらでも書いておきます。)

以下の3ファイルを用意します。

connect 'jdbc:derby:c:/tmp/derby/dat/test;user=admin;password=admin;create=true';
connect 'jdbc:derby:c:/tmp/derby/dat/test;user=admin;password=admin';

MAXIMUMDISPLAYWIDTH 15;

--DROP TABLE users if needed

show tables in admin;

CREATE TABLE users (
    id INT NOT NULL PRIMARY KEY
        GENERATED ALWAYS AS IDENTITY
        (START WITH 1, INCREMENT BY 1),
    login_id VARCHAR(20) NOT NULL,
    password VARCHAR(20) NOT NULL,
    user_name VARCHAR(20) NOT NULL,
    birthday CHAR(8),
    email VARCHAR(40) NOT NULL,
    address VARCHAR(200),
    credit_card_number CHAR(16),
    authority_type CHAR(1) NOT NULL,
    is_deleted CHAR(1) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_by VARCHAR(20) NOT NULL
);

CREATE UNIQUE INDEX ui_users_01 ON users (
    login_id
);
CREATE UNIQUE INDEX ui_users_02 ON users (
    email
);
CREATE UNIQUE INDEX ui_users_03 ON users (
    credit_card_number
);

show tables in admin;
describe users;

commit;

connect 'jdbc:derby:c:/tmp/derby/dat/test;user=admin;password=admin';

MAXIMUMDISPLAYWIDTH 15;

select * from users;

INSERT INTO users VALUES 
(DEFAULT, 'sj', 'berkay', 'sercan', '20000318', 'sercan@gmail.com',
'19 Mc Cabe Street', '1234567890123456', '1', '0', current_timestamp, current_timestamp, 'admin');
INSERT INTO users VALUES 
(DEFAULT, 'br', 'ugur', 'oljay', '19980322', 'oljay@gmail.com',
'19 Mc Cabe Street 2145', '1234567890123450', '1', '0', current_timestamp, current_timestamp, 'admin');

select * from users;

commit;

※参考のサイト様と違い、全てCドライブのTOOLというフォルダで作業しています。

作成したファイルを使ってデータを投入します。

derbyのbinフォルダ内から、以下のコマンドを実行。

C:\TOOL\derby-10.14.2.0\bin>ij C:\TOOL\derby-10.14.2.0\script\createDatabase.sql
C:\TOOL\derby-10.14.2.0\bin>ij C:\TOOL\derby-10.14.2.0\script\createUserTable.sql
C:\TOOL\derby-10.14.2.0\bin>ij C:\TOOL\derby-10.14.2.0\script\insertUser.sql

Derbyにアクセス

derbyと一緒に入っているijというツールでアクセスします。

derbyのbinフォルダ内で、以下のコマンドを実行すると、ちゃんと検索できました!(当たり前)

C:\TOOL\derby-10.14.2.0\bin>ij
ijバージョン10.14
ij> connect 'jdbc:derby:c:/TOOL/derby/dat/test;user=admin;password=admin';
ij> select * from users;
ID         |LOGIN_ID            |PASSWORD            |USER_NAME           |BIRTHDAY|EMAIL                                   |ADDRESS                                                                                                                         |CREDIT_CARD_NUM&|&|&|CREATED_AT                   |UPDATED_AT                   |UPDATED_BY
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1          |sj                  |berkay              |sercan              |20000318|sercan@gmail.com                        |19 Mc Cabe Street                                                                                                               |1234567890123456|1|0|2019-01-09 13:32:16.368      |2019-01-09 13:32:16.368      |admin
2          |br                  |ugur                |oljay               |19980322|oljay@gmail.com                         |19 Mc Cabe Street 2145                                                                                                          |1234567890123450|1|0|2019-01-09 13:32:16.389      |2019-01-09 13:32:16.389      |admin

2行が選択されました

Derbyの起動モード

DervyにJavaからアクセスる前に、起動モードについておさらいです。

Derbyには起動モードがあり、組み込みDB用の起動とクラサバ用起動の2種類があります。

違いとしては、

起動モード起動方法特徴接続URLライブラリ
組み込み用起動不要1つのアプリケーションのみがアクセス可能jdbc:derby:C:/TOOL/derby/dat/testderby.jar
クラサバ用start startNetworkServer.bat通常のRDBMSの様に複数のアプリケーションからアクセス可能jdbc:derby://localhost:1527/C:/TOOL/derby/dat/testderby.jar
derbyclient.jar

はまりポイント

1.権限が無いフォルダにDBを作ってしまい、操作できない

凡ミスです。自由に操作できる場所にDBを作るようにしましょう。

2.クラサバモードで起動すると、JavaアプリからDBにアクセスできない

Javaからアクセスすると、以下のエラーが出ました。

java.sql.SQLException: DERBY SQL error: ERRORCODE: 0, SQLSTATE: XJ001, SQLERRMC: java.security.AccessControlExceptionaccess denied ("java.io.FilePermission" "C:\tmp\derby\dat\test" "read")XJ001.U
	at org.apache.derby.client.am.SQLExceptionFactory.getSQLException(Unknown Source)
	at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
	at org.apache.derby.jdbc.ClientDriver.connect(Unknown Source)
	at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:117)
	at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:123)
	at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:365)
	at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:194)
	at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:460)
	at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:534)
	at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115)
	at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112)
	at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:151)
	at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:115)
	at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:78)
	at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:319)
	at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:356)
	at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72)
	at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:166)
	at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:111)
	at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$EnhancerBySpringCGLIB$d4af053c.CGLIB$jpaVendorAdapter$5(<generated>)
	at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$EnhancerBySpringCGLIB$d4af053c$FastClassBySpringCGLIB$7c52b6f9.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:365)
	at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$EnhancerBySpringCGLIB$d4af053c.jpaVendorAdapter(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)


原因は非常にシンプルでした。DBの起動は、start startNetworkServer.batで実施するのですが、このバッチに問題があります。

通常、何も指定せずに起動すると、このバッチは全く想定外の所のデータベースを参照しに行くようになります。(自分の無知が原因だが、起動に失敗してくれよとは思う。)

よって、起動バッチに作成したDBの場所を教えるコードを追加する必要があります。

startNetworkServer.batに以下に修正(6行目を追加)。

CALL "%~dp0derby_common.bat" %*


if "%_JAVACMD%"=="" goto end

SET DERBY_OPTS=-Dderby.system.home=c:\tmp\derby ← この行を修正

if "%_USE_CLASSPATH%"=="no" goto runNoClasspath
if not "%CLASSPATH%"=="" goto runWithClasspath

:runNoClasspath
"%_JAVACMD%" %DERBY_OPTS% -classpath "%LOCALCLASSPATH%" org.apache.derby.drda.NetworkServerControl start %DERBY_CMD_LINE_ARGS%
goto end

:runWithClasspath
"%_JAVACMD%" %DERBY_OPTS% -classpath "%CLASSPATH%;%LOCALCLASSPATH%" org.apache.derby.drda.NetworkServerControl start %DERBY_CMD_LINE_ARGS%
goto end

:end
set _JAVACMD=
set DERBY_CMD_LINE_ARGS=


これでうまくいきました。
バッチを直接弄るのはあまり良くないので、緊急対応として・・・実行時の引数にするとか、環境変数に定義するとかしましょう。

3.Webアプリ起動時に No identifier specified for entityが発生する
これも凡ミス。
Entityクラスでプライマリキーを示す@Idアノテーションを付与しているのですが、

import org.springframework.data.annotation.Id;

が指定されていました。

正しくは、

javax.persistence.Id

###############お知らせ################
ブログランキングのITカテゴリに参加してみました。
この記事が役に立ったなどお力になれたら、 このバナーを押していただけると嬉しいです。

#####################################

-Java