このページに書いてあること。
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/test | derby.jar |
クラサバ用 | start startNetworkServer.bat | 通常のRDBMSの様に複数のアプリケーションからアクセス可能 | jdbc:derby://localhost:1527/C:/TOOL/derby/dat/test | derby.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