PostgreSQLをデータベースとしたサーバー&クライアント型試薬管理システム(Servo)の開発

末永 正彦


Return

1 はじめに

大学における試薬管理は、これまで企業におけるそれと比べてたいへん遅れていた感があるが、一連の毒物事件により試薬管理の見直しが社会的に要求されることになり、本大学でもそれに応える形で施錠のできる試薬庫が導入された。それを機に、本研究室でも試薬のリストと各試薬の使用記録簿の作成をパソコンを利用して行うことが検討されたが、市販の試薬管理システムが高価であるため、試薬管理システムをJava言語とPostgreSQLにより自作した。

2 市販のシステムとの比較

市販の試薬管理システムである東北緑化環境保全株式会社のIASO 2000 [1]と本システムを比較してみる。バーコードと電子天秤とパソコンを連動させたシステムでネットワークを通じてデータのやり取りを行い、試薬管理のデータベースを一元管理しているシステムであるという点では同じであるが、IASO 2000はWindows上のクライアントであるのに対し、本システムはJavaで記述されているため、電子天秤の接続など一部のOSに依存する機能を除いて、プラットホームに依存しない。ただし、試薬データの確認に関して、IASOではクライアントとは別にWebブラウザ−を使うこともできる。また、試薬の使用状況・履歴についても「いつ」「誰が」「どの薬品を」「どんな目的」で使用したかを記録する点でもGUIは別にして基本的に同じである。異なる点としては、以下のものが挙げられる。
IASO 2000では、試薬の基礎情報(メーカー、使用期限、毒劇物か否か、構造式、物性など)を試薬ラベルのバーコードから読み込み、データベースにあるこれらのデータを表示させ、試薬管理用のデータベースにもそれがそのまま使えるが、本システムにはその機能がない。
IASO 2000では、試薬の重量の異常増減などをクライアントの画面上の該当箇所に赤く点滅させるアラーム機能があるのに対し、本システムでは実装していない。これは、異常増減には登録のし忘れや間違った値の入力などユーザーの誤操作によるものが多く、これらを本当の異常と区別するのが難しいため、異常を判定する基準をまだ決めていないという理由による。
またIASO 2000 では、電子式試薬保管庫(ナガノ科学機械製作所)、入室管理システム(富士通電装)、鍵管理システム(株式会社クマヒラ)とIASO 2000を組み合わせたセキュリティシステムをオプションとして用意している。試薬管理を厳密に行う場合、各ユーザーの申告制による試薬の出し入れの記録では不十分で、試薬庫の開閉そのものを記録したり、試薬室への入室を記録するようなセキュリティシステムが必要となる。このような機能は、本システムにはない。
結論として本システムは、セキュリティシステム以外の機能では、ほぼ同じ機能を有するので簡易的な試薬の管理では十分利用できると思われる。

3 管理システムを自作する利点

試薬管理システムのようなデータベースクライアントは、データベースの構造(テーブルの数や、テーブルを構成するフィールドの数やその属性)に強く依存しているため、データベースの構造を変更した場合(例えば、新たなフィールドを追加した場合)、クライアント側も書き換えることが必要になる。市販のシステムで用意されているデータベースの仕様に、ユーザーが望む必須項目がない場合、システムの書き換えを依頼することになる。このようなカスタマイズの要望は各社有償で受け付けているようであるが、自作している場合、このような変更を簡単に素早く行うことができる。また、データベースの構造の変更ではなく、データベースそのものをPostgreSQLから別のデータベースに取り替える場合も簡単に行うことができる。すでに別の目的で運用しているPostgreSQL以外のデータベースを用いて試薬の管理もいっしょに行おうとする場合でも、移行は容易である。このほかクライアントの使い勝手の細かな変更なども、自作している場合には自由にできるので、利用者がより使い易いと思われるシステムに仕上げていくことができる。
このようにシステムを自作した場合、システム仕様の変更、拡張を自由に行うことができるのが最大の利点である。

4 システム構成

本試薬管理システムは、Figure 1に示すように、データベースを管理するサーバー部分とデータベースへの入出力インターフェイスとなるクライアントからできている。データベースはRedHat Linux 6.1上で稼働するPostgreSQL 6.5.1を使用した[2]。クライアントはJava言語で新たに開発し、Windows上で稼働している[3]。システムをサーバー&クライアント型としたことで、データベースを一元化することができ、同時に多くのユーザーがデータベースのあるマシンとは別の離れたところにあるマシンからネットワークを経由して利用することが可能になった。実際の試薬の管理はそれぞれの試薬瓶に貼ったバーコードをもとに、試薬瓶の重量も含めた全量の変化を記録して行う。バーコード入力の軽減のため、クライアントマシンにはバーコードリーダーがつながっている。また、電子天秤もシリアルポートを介してRS-232Cでつながっており、試薬瓶の重量の入力が自動化されている。


Figure 1. System diagram

5 クライアントの概要

クライアントは目的別(登録、使用、返却、試薬検索、履歴検索、破棄、シリアルポートの開閉、データベース保守)に独立した8個のフレームとサーバーからの応答を表示する2個のフレームおよび全フレームの表示を切り替えるコントロールフレーム(Figure 2)から成っている。各フレームのGUIはJava Swing [4]を用いて作成したが、SwingのLook&Feelとは若干異なり、画像を多く使用した独自のものに仕上げた。またフレーム毎に背景の色を変え、どの操作をしているのか直感的に区別できるようにした。


Figure 2. Control frame

以下、コントロールフレームにあるボタンの順に、各フレームを簡単に説明する。
Figure 3からわかるように、バーコード、試薬名、化学式、瓶を含めた全体の重さを入力し、試薬の分類(Category)、部屋、試薬庫をリストから選択して、試薬を登録する。試薬の所有者は、デフォルトでは「全員」になっている。また、試薬瓶の風袋、試薬の正味の重量は、不明な場合は入力しなくてもよい。コメントも必須ではない。登録に使うバーコードはデータベースの中では整数として取り扱っているので、数字で表される規格のものであればよい。また、試薬の分類(Category)は、「毒物及び劇物取締法」による区分に従い、劇物(Hazardous)、毒物(Toxic)、その他(Others)の3つとしている。


Figure 3. Registration frame

試薬の使用、返却は、それぞれ別のフレーム(Figures 4, 5)を使い、必要最小限のデータだけが表示されるようにしてある。試薬を返却する際のユーザー確認は、現在のところ行わない仕様にしており、履歴には、「Last Userが返却した」と記録される。


Figure 4. Use frame


Figure 5. Return frame

使用、返却に伴うデータベース更新の際にPostgreSQLから返されるメッセージや不適当なデータの入力に対するエラーは、Figure 6に示されるフレームにすべて表示される。


Figure 6. Reply frame

試薬の検索はFigure 7に示されるようなフレームを使う。検索の条件は各項目に続くテキストフィールドに条件を書くことにより設定される。空白は「条件設定なし」の意味になる。従って、何も入力せずに検索させると全ての試薬が表示される。また、条件となる文字列は大文字と小文字が区別されるため、例えばSodiumで登録してある試薬をsodiumで検索してもヒットしない。そのため、登録作業を大人数で手分けして行う場合、試薬名は「頭文字だけ大文字にする」といったような規則を作り試薬名の表記法を統一したほうがよい。また検索画面のチェックマークの有無は、その項目を検索結果のなかで表示するかどうかという意味であり、その項目で条件を付けるかどうかという意味ではない。検索結果の並べ替えはデフォルトでは、バーコードの大きい順にしてあるが、他の項目でも並べ替えができる。


Figure 7. Reagent search frame

試薬の履歴は、Figure 8のようなフレームで行う。検索における条件の入れ方やチェックマークの意味は、試薬検索で述べたのと同じである。特定の試薬の全ての履歴(登録、使用、返却、廃棄等)をみるには、バーコードのみを入力し、検索させる。何も入力せずに検索させると全ての試薬の全ての履歴が表示される。日時、ユーザー名や登録、廃棄などのイベントによる絞込み検索もできる。


Figure 8. History search frame

試薬の廃棄手続はFigure 9に示すフレームで行う。機能的にはFigures 4, 5に示した試薬の貸出しや返却と同じだが、どの手続をしているのか明確にし、間違いが少なくなるようにするため、これらは別々のフレームにしてある。


Figure 9. Discard frame

シリアルポート設定、開閉はFigure 10に示すようなフレームで行う。これは、Java Communications APIに付属のDemoに電子天秤との通信を行う部分を付け加えて作った。電子天秤の読みを表示させるためには、ポート名やBaud Rate等を設定した上で、"Open Port"ボタンによりシリアルポートをオープンしておかなければならない。


Figure 10. Serial connection frame

データベースへの誤入力をクライアント側で修正するためのフレームがFigure 11に示されている。バーコードを入力し"Retrieve the data"ボタンをクリックすると相当する試薬のデータ(テーブルreagentsのデータ)がすべて表示されるので、これを修正する。試薬の履歴(テーブルhistoryのデータ)は、クライアント側では修正できない。データデータベースの修正はこのフレームでの作業のほか、7.3で述べるようにテキスト化されたデータベースに対して行う方法もある。試薬の履歴の修正は、テキスト化されたデータベースを修正しなければならない。


Figure 11. Maintenance frame

試薬検索、履歴検索のフレームでチェックマークを入れた項目の検索結果は、Figure 12のようなテーブルの形で表示される。この表のそれぞれのカラムの幅は、項目を区切る縦線をドラッグすることにより変えることができる。また結果は、テキストファイルとして保存できる。


Figure 12. Result frame

6 クライアントの設定

6. 1 ユーザー名などの登録

保管場所、試薬庫の番号、ユーザー名は、JavaソースファイルConstants.javaの中で定数LOCATION1, LOCATION2, USERSとして定義されているので、その登録はこれらの定数を設定することにより行う。
データベースのURL(あるいはIPアドレス)、およびデータベースにログインする際に必要なログイン名(上で述べたユーザー名とは別)とそのパスワードは、7.4の「データベースのセキュリティ」で説明してあるログイン名とパスワードのことで、ソースファイルDBConfigure.javaの中で定数URL, USER, PASSWDとして定義されている。その登録はこれらの定数を設定することにより行う。
以上の登録作業は、Javaのソースファイルを変更するので、使用するためには再コンパイルが必要となる。

6. 2 管理ユーザーのパスワードの登録

本システムでは、管理ユーザーというものを特には設けていない。ただ、Figure 11で示したデータベースの修正フレームを表示する際、パスワードによる制限を設けているだけである。したがってこのパスワードが実質的な管理ユーザーのパスワードということになる。このパスワードはJavaソースファイル Constants.javaの中で定数SUPERPASSWDとして定義されている。ただし、パスワードの文字列がそのまま入る訳ではなく、MD5によりダイジェスト化された32桁の16進数が入っている。ダイジェスト化は、例えばLinux上のmd5sumコマンドにより行う。
この登録作業もまた、Javaのソースファイルを変更するので、使用するためには再コンパイルが必要となる。

6. 3 JDBCドライバ

JavaからPostgreSQLを使うためには、JDBCドライバーが必要である。注意しなければならないことは、Java コンパイラとPostgreSQLの双方のバージョンに適合したドライバーを使う必要があるということである。下記のJDBCのサイト
http://jdbc.postgresql.org/download.html
に適当なドライバーの圧縮アーカイブが置いてあるので、ダウンロードして使用する。ちなみに、著者が使用したJDK 1.1.8 とPostgreSQL 6.5.1の組合せでは、ダウンロードのページにあるPostgreSQL 6.5.2 JDK 1.1.x を選択して、jdbc6.5-1.1.jar をダウンロードした。この圧縮アーカイブを解凍して得られるpostgresql というフォルダーは、フォルダーごとServoのClassファイルのあるフォルダー内に置いておかなければならない。

6. 4 周辺機器

天秤の読みを自動的にパソコンに取り込むため、天秤とクライアントマシンがRS-232Cで接続されている。通信手段としてはMT-SICS (METTLER TOLEDO Standard Interface Command Set)を用いている。MT-SICSは、METTLER-TOLEDO社が開発した電子天秤を制御するためのコマンド群である。本システムで使用しているMT-SICSのコマンド S は「安定している現在の重量の値を送信せよ」という命令である。"S"という文字を二秒毎にシリアルポートを介して天秤側に送信することにより、送り返される文字列の中から重量を表す数値を取り出して表示している。MT-SICS以外の通信手段を使用する場合には、天秤から返信されるデータのフォーマットに応じて若干の変更が必要となる。Javaからシリアルポートを使うためには、Java Communications APIが必要となる。これは、
http://java.sun.com/products/javacomm/index.html
からダウンロードできるが、対応しているOSは、現在のところWindowsとSolarisだけである。したがって、クライアントをMacintosh上で稼動させる場合、シリアルポートに関する部分を削除しておかなければならない。
このほか、バーコードの入力を軽減するためバーコードリーダーが接続されている。用いたのは、オプトエレクトロニクス社のキーボードインターフェイスバーコードスキャナ(OPT-WEDGEシリーズ)であり、これはパソコン本体とキーボードの間に接続するだけで使用できる。

7 サーバーの設定と保守管理

7. 1 データベースの構成

データベースは二つのテーブル(ReagentsとHistory)で構成されている。テーブルの定義は、PostgreSQLのコマンドの形で示すとList 1, 2のようになる。テーブルReagentsでは、すべての試薬の現時点での状態だけを記録する。したがって一つの試薬にただ一つのデータがある。そのためBarcodeの項目には重複がないようprimary key が指定してある。対照的に、テーブルHistoryでは各試薬の履歴を全部記録するため、一つの試薬に履歴の数だけデータがある。従ってテーブルHistoryのBarcodeのデータは重複があってもよい。「not null」が指定してあるものは、空白が不可な項目である。またCurrentTotalWeightのように常に0.00g以上であるべきような項目は、checkの後に続く括弧内の条件に適合するかどうかが、更新時にチェックされる。TotalConsumptionは0.00gの場合もあるので、-0.01gを下限としてチェックをしている。
CREATE  TABLE  Reagents (
 Barcode             int   primary key,
 Reagent             text  not null,
 Formula             text  not null,
 InitTotalWeight     real  not null,
 Tare                real,
 InitNetWeight       real,
 LastTotalWeight     real
      not null check(LastTotalWeight> 0.00),
 CurrentTotalWeight  real
      not null check(CurrentTotalWeight> 0.00),
 TotalConsumption  real
      not null check(TotalConsumption>-0.01),
 Category            text  not null,
 Location1           text  not null,
 Location2           text  not null,
 Owner               text  not null,
 CurrentUser         text  not null,
 Comment             text,
 Status              text  not null
);
List 1. テーブルreagentsの定義
CREATE  TABLE  History (
 Barcode              int     not null,
 LastTotalWeight      real    not null,
 CurrentTotalWeight   real    not null 
             check (CurrentTotalWeight > 0.00),
 Who                  text    not null,
 DateStamp            text    not null,
 TimeStamp            text    not null,
 What                 text    not null
);
List 2. テーブルhistoryの定義

7. 2 データベースの作り方

データベースは、Linux上で、PostgreSQLのインタープリタであるpsqlを使い対話的に作成する。ただし、PostgreSQLが既にインストールされており、クライアントからの要求を受付けるpostmasterというデーモンが起動しているものとする。
まず、List 1, 2にある二つのテーブルの定義をそれぞれテキストファイル reagents.sql とhistory.sqlに保存する。Linuxのシェルからcreatedb servodbと入力し、servodbという名のデータベースをつくる。次にシェルからpsql servodbと入力し、psqlを起動する。psqlのプロンプトがでるので、 \i reagents.sql; と入力する。同様に \i history.sql; と入力する。これで、二つのテーブルが新たに作成される。生成したテーブルの確認は、psqlのプロンプトから \d reagents; あるいは  \d history; を入力して行う。最後に \q と入力し、psqlを終了する。以上の操作で二つのテーブルReagentsとHistoryを持つデータベース servodb ができる。

7. 3 サーバー側でのデータベースの保守

データベースをテキストファイルとして残すには、pg_dumpコマンドを使う。Linuxのシェルからpg_dump servodb > servodb.pgdumpを実行するとservodbというデータベースの内容が、servodb.pgdumpというファイル名で保存される。このファイルはテキストファイルなので、データの削除や追加など編集ができる。pg_dumpコマンドにより作成したテキストファイル化したデータベースを読み込み、データベースを復元するには、つぎのコマンドをLinuxのシェルから実行する。
cat servodb.pgdump | psql servodb
テキスト化したデータベースを編集する際には、空白に関しSpaceとTabの使い分けに注意する必要がある。例えば、次の様なデータベースがあった場合、

IDNAMEAGE
1Amidala\N
2Anakin Skywalker8

各項目(ID, NAME, AGE)を分けている空白はTabでありSpaceではない。「Anakin Skywalker」のように空白を含む文字列では、空白としてはSpaceを使い、Tabを使ってはならない。また、データがない項目には \N が入っているが、この部分を空白にしてはならない。空白の取り扱いを間違えるとテキストファイル化したデータベースを再び読み込んでデータベースを復元する際にエラーがでてうまくできない。

7. 4 データベースのセキュリティ

データベースへのアクセス制限の条件は、pg_hba.connf に記述する。このファイルはPostgreSQLのインストール時に既に作成されている。この中のhostの部分にアクセスの制限を記述する。 例えば、

localalltrust
hostall0.0.0.00.0.0.0passwordpasswd

と書くと、データベースのあるマシンからは何の制限もなくアクセスでき、ネットワークを介したアクセスはパスワードによる制限がかかる。ここで、passwd はPostgreSQLへ接続する時に必要なパスワードであり、シェルから pg_passコマンドを実行することでログイン名とともに設定することができる。このpasswd はクライアントがサーバーにログインする場合に使われるため、6. 1で説明した定数PASSWDに設定する。
このほかIPアドレスによるアクセス制限も行うことができ、0.0.0.0 0.0.0.0 の部分を例えば、
192.168.0.1 255.255.255.255 と書くと、
192.168.0.1 からのアクセスのみが許可される。

8 今後の改良点

現在のシステムは、ユーザー名、試薬庫などデータベースを実際に使用するにあたって必要な項目をJavaソースファイルの中で定数として定義しているため再コンパイルを必要としているが、設定に必要な項目はすべてテキストファイルとし、クライアントの起動時にそれを読み込むことで設定できるように変更するのがよいと思われる。また、本システムは、筆者の所属する研究室で使用するため作成したものであるので、パスワードによるアクセスの制限を非常に緩やかなものにしてあるが、今後は厳しい制限でも緩やかな制限でも、どちらにも簡単に対応してカスタマイズできるようなシステムにすべきである。
その他の問題点としては、PostgreSQLを動かしているLinuxマシンがダウンした際に代替となるLinuxマシンが用意できない場合、試薬管理システムがダウンするということが挙げられる。Linuxマシンよりも研究室に多くあるWindowsマシンをデータベースサーバーにすることができれば、代替マシンが見つけ易くなると思われる。また、試薬データベースを定期的に保存するなどの作業もLinuxに慣れた管理者がいなくなった場合、行われなくなる可能性が高くなる。サーバーマシンがWindowsであれば、このような問題も少しは軽減されると思われる。したがって、Windows上でも動くデータベースをもとにした試薬管理システムを作ったほうが、マシンのクラッシュに強く、管理や保守のし易いシステムになると考えられる。候補となるデータベースとしてMySQLが挙げられる。これは、高速で堅牢なマルチユーザー・マルチスレッドのSQLデータベースであり、無償で利用できる。次のバージョンは、このMySQLをもとに作成する予定である。

9 ソフトウェアの配布

Servo (Ver.3.0)はJavaソースコードを含め全てフリーで著者のホームページよりダウンロードできる。
http://hb6.seikyou.ne.jp/home/zzzfelis

参考文献

[ 1] IASO 2000のカタログ、東北緑化環境保全株式会社.
[ 2] 石井達夫, PostgreSQL完全攻略ガイド, 技術評論社 (1999).
[ 3] George Reese 著、古賀直樹 監訳、川村史記、鶴町重夫 共訳, JDBCによるJAVAデータベースプログラミング, オライリージャパン (1998).
[ 4] Satyaraj Pantham 著、 岩谷 宏 訳, 速習Java Swingプログラミング, SOFT BANK Publishing (1999).


Return