動機
先月から折れ線グラフで表示するプログラムをJavaFXで作っています(自宅や出張中の宿で細々とです。出張先では通勤時間とか家事とかがないので捗りました)。
スペクトラム・アナライザのデータをファイルから読み込む機能を持たせていますが、ファイルの数が増えてくると、ファイルの管理が大変になります。例えば、どの信号を解析したものか、それはいつのものか、解析に使った計測器は何か、計測時の条件はどうだったか、などなどをファイルと関連付けて管理しなくてはなりません。
ディレクトリ名とファイル名を工夫する等で多少は関連付けを表現できます。解析対象、計測器、計測日時などをディレクトリとし、条件をファイル名にする、といった工夫です。
信号種類A \ XWV8765-BA \ 20190818-02-51 \ ATT15_SPAN100M_RBW20K_GX.trace
しかし、単一ツリーのディレクトリ管理ではやがて限界に達してしまいます。特にディレクトリの底の条件、ファイル名に含んだ条件を探すときなどです。
そこで、データベースを使ってこれらのデータを系統立てて保存・管理し、表示したいデータを条件を指定してすぐに取り出せるようにします。
データは、ローカルなネットワーク上に置いて複数台のクライアントから利用可能とします。
どんなデータベースを使うか?
スペクトラム・アナライザのデータ(スペクトラム・アナライザの画面に表示されるある瞬間のデータ)は、1GHzの周波数範囲をRBW 20KHzで取得していた場合、 5万点の点列データとなります。周波数とパワー(X軸とY軸)を1点ごとに1レコードで管理すると1回分で5万レコードになります。1時間に1回計測があるとしたら、年間で1台あたり4億レコード超といった計算になります(10秒に1回だと1兆レコード超え)。
もしリアルタイムにこのレコードを記録し検索するのであれば、時系列データベースなどを使うことを検討します。
今回はスペクトラムデータを、計測条件を指定して取り出し表示するアプリケーションで使うことが主なユースケースとなります。スペクトラムデータの格納はオフラインで別途行うため、書き込みは検討外とします。 そこで、条件を指定してデータを取り出すことに向いていると考えるRDBMSを使うことにします。
ただし、点列データを1点1点レコードに入れるとサイズが増大してしまいますので、データベース設計上の課題とします。解決方針は、1回分の点列データをバイナリデータとして1つのレコードに格納します。 点列データの利用方法は、1回分のデータを一括して取り出すもので、点列データの中の特定の値だけ検索して取りだすことはないためです。(アプリケーションの機能として点列データの一部を切り取ることはありますが、データベースには要求しません)
データベースと開発ツール
RDBMSの選択
今回は、ゼロベースの選定はしません。既にある計測器の中で使われており、またローカルのネットワーク上に既にインストールしているデータベースにMicrosoft SQL Serverがあるので、それを使うこととします。
SQL Serverは、大規模(高スペックなサーバー上で稼働)用のEnterprise Edition、中規模用のStandard Editionがあり、それぞれ有償ライセンス(180日間の試用期間あり)となっています。また、小規模(1つのデータベース領域<10GB)のExpress Editionが無償ライセンスで提供されています。開発・テスト用にはDeveloper Editionが無償で提供されています。
SQL Serverの開発環境
開発用に、Express EditionあるいはDeveloper Editionを開発マシンに入れると便利です。 管理ツールとして、SQL Server Management Studio(SSMS)を合わせて入れます。
データベース設計用にはER図も使えるA5:SQL Mk-2を入れてみます。これはWindows用のみですが、無償で利用可能です。自宅環境なのでこれを使うことにしました。
仕事上であれば、有償のデータベース設計用ツールも視野に入れて、ER/Studio、ERWin、SI Object Browserなども候補に挙げるといいかと思います。
JavaからSQL Serverの利用
SQL Server用のJDBCドライバーがMicrosoftから提供されています。
JavaからRDBMSを使うときのAPI選定
Java(Java SE)からRDBMSを使うときに、APIとしていくつかの選択肢があります。
- JDBC APIを使う JDBCドライバーを入れて、Java SE標準のJDBC APIを使いDBとデータをやり取りする方法
- Java Persistent API(JPA)を使う JPA仕様に準拠したサードパーティ・ライブラリ(eclipselink等)を使い、JPAのO/Rマッパー経由でDBとデータをやり取りする方法
- サードパーティ・ライブラリ独自APIを使う 標準APIではなく、サードパーティ・ライブラリが独自に提供するAPIを使います。いろいろ種類がありますが、おおざっぱに分類すると
今回のAPI選定基準
次の観点を選定基準にします。
- Java SE 以外のサードパーティ・ライブラリへの依存を少なくしたい
- アプリケーションのソースコード構成を簡潔に保ちたいので自動生成のソースや設定ファイルは極力無にしたい
- RDBMSでのテーブル(スキーマ)設計、SQLの書き方をこの機に勉強したい
RDBMSの勉強を上げたのは、RDBMSのアプリ開発での利用経験が少ないからです。 これまでのソフトウェア開発経験で使ったデータベースは、Microsoft AccessのJETエンジン、ObjectStore DB(OODBMS)です。Oracle、SQLite、MySQL、H2 Database Engine(+JPA)は開発インフラとして整備、チューニングに携わりましたが、これらDBをアプリから使う開発はあまりしていません。 ソフトウェア開発とは別に、Redmineの環境構築・運用管理でMySQLを扱っているので、RDBMSの素養はRedmineの管理経験に拠るところが大きいです。
JDBCドライバーを使ってDBアクセス
Java SEのJDBC APIでは、まず使用するデータベース用のJDBCドライバーを入れる必要があります。
SQL Server用のJDBCドライバーの入手
Microsoft SQL Serverについては、MicrosoftからType 4 JDBCドライバーが提供されています。
Microsoft SQL Server 用 JDBC Driver のダウンロード - SQL Server | Microsoft Docs
2019-08-18時点では、最新バージョン7.4.1がリリースされています。これは、
- JDBC仕様 4.2対応
- JDK 12, 11, 8対応
- Java Platform Module System(JPMS)向けにAuto-Module-Nameで@com.microsoft.sqlserver.jdbc@として公開(JDBC Driver 7.0以降)
となっています。
これをダウンロードし、適切なディレクトリに展開します(リリースノートではC:\Program Files下を推奨)。今回は、@C:\Program Files\Java\sqljdbc_7.4@に展開しました。 JDK 8用、JDK 11用、JDK 12用のJARファイルが存在します。
mssql-jdbc-7.4.1.jre8.jar mssql-jdbc-7.4.1.jre11.jar mssql-jdbc-7.4.1.jre12.jar
JDK 11で使用する場合
Javaのコンパイル、実行時にモジュールパスにJDBCドライバーのJARファイルを指定します。
C:\work> javac -p "C:\Program Files\Java\sqljdbc_7.4\mssql-jdbc-7.4.1.jre11.jar;out\myapp" ...
JDBC APIを使ったプログラミング
JDBC 4.0(Java SE 6以降)では、JDBCドライバーがクラスパス上にあれば次の2つの方法で接続します。
- DriverManager を使う
- DataSource を使う
JDBCのドキュメントによると、DriverManagerよりもDataSourceが推奨されています。ソースコードにデータベース接続設定(ホスト、ユーザー、パスワード等)を記述するDriverManagerよりも、JNDIで接続する外部(ディレクトリサーバー等)に設定を置くDataSourceがよいということです。アプリケーションサーバー上で実行する場合は簡単に利用可能です。
しかし、Java SE 環境では、 JNDI経由でDataSourceを使うのは敷居が高いので、DriverManagerを使う方法で実装します。