1.ユーザーが画面上で操作したことによる値を取得
2.データベースを操作するためのSQL文を作成
3.データベースを操作
4.データベースからの結果を画面に表示
実はSQL文さえできれば、データベースを操作するのはそれほど難しくありません。一番複雑なのは 1 です。画面上の部品からいかに値を取得して、SQL文を組み立てられる状態にするかです。
そこで今回は 1 と 2 に専念することにします。具体的にはボタンやメニューを選択した時に、あらかじめリストから取得しておいた値をもとにダイアログボックスを表示させます。
そしてダイアログボックスから取得した値も組み合わせて、データベースを操作するためのSQL文を作成します。作成したSQL文は確認のため、コマンドプロンプトに表示します。
SQL文は表示するだけで実行しませんので、データベースには影響ありません。どんどん画面を操作して、SQL文が自動的に組み立てられることを試してください。
本来は入力したデータが適切かどうかチェックしたり、例外処理も必要ですが、まずは大きな流れをつかんでもらいたいため、あえて省略していますのでご了承ください。
【1】sample214 フォルダをフォルダごとコピーして、sample215 フォルダを作ります。
【2】今回は以下のようなファイル構成になりますので、コピーした余計なものは削除してください。
*SampleDb030.class を忘れないようにしてください。
【3】PrefTest.java を以下のように変更します。
*「\」はWindowsではエンマークのことです。
保存先 C:\java\sample215
ファイル名 PrefTest.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.sql.*;
import java.util.*;
class PrefFrame extends JFrame implements ActionListener, ListSelectionListener {
Container cp;
JLabel lb1;
JList lt;
JButton btn1, btn2, btn3, btn4;
JMenuItem mi1, mi2, mi3, mi4, mi5, mi6;
String[] tkn;
public PrefFrame(String title) {
//フレームのタイトル
setTitle(title);
//コンテンツペイン取得
cp = getContentPane();
//ウィンドウを閉じる時
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
showExitDialog();
}
});
//Look&Feelの設定
/*
String type = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
try {
UIManager.setLookAndFeel(type);
} catch ( Exception e ) {
System.out.println("例外発生:" + e );
}
*/
//メニューバーの生成
JMenuBar mb = new JMenuBar();
//メニューの生成
JMenu mn1 = new JMenu("ファイル");
JMenu mn2 = new JMenu("編集");
JMenu mn3 = new JMenu("検索");
//メニュー項目の生成
mi1 = new JMenuItem("追加");
mi2 = new JMenuItem("更新");
mi3 = new JMenuItem("削除");
mi4 = new JMenuItem("終了");
mi5 = new JMenuItem("検索");
mi6 = new JMenuItem("全件表示");
//イベントリスナーの登録
mi1.addActionListener(this);
mi2.addActionListener(this);
mi3.addActionListener(this);
mi4.addActionListener(this);
mi5.addActionListener(this);
mi6.addActionListener(this);
//メニューへの追加
mn1.addSeparator(); //セパレーター
mn1.add(mi4);
mn2.add(mi1);
mn2.add(mi2);
mn2.add(mi3);
mn3.add(mi5);
mn3.add(mi6);
//メニューバーへの追加
mb.add(mn1);
mb.add(mn2);
mb.add(mn3);
//メニューバーをフレームへ追加
setJMenuBar(mb);
//ラベル
lb1 = new JLabel("ボタンをクリックしてください。", SwingConstants.CENTER);
lb1.setOpaque(true);
lb1.setFont(new Font("Dialog", Font.PLAIN, 12));
lb1.setBackground(Color.WHITE);
lb1.setForeground(Color.BLUE);
cp.add(lb1, BorderLayout.NORTH);
//リスト
lt = new JList();
lt.setFont(new Font("Dialog", Font.PLAIN, 14));
lt.setForeground(new Color(64, 64, 64));
lt.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lt.addListSelectionListener(this);
JScrollPane sp = new JScrollPane(lt);
cp.add(sp, BorderLayout.CENTER);
//パネル
JPanel pn1 = new JPanel();
pn1.setLayout(new GridLayout(1, 4));
//ボタンの設定
btn1 = new JButton("追加");
btn2 = new JButton("更新");
btn3 = new JButton("削除");
btn4 = new JButton("終了");
btn4.setForeground(new Color(255, 0, 0));
btn1.addActionListener(this);
btn2.addActionListener(this);
btn3.addActionListener(this);
btn4.addActionListener(this);
pn1.add(btn1);
pn1.add(btn2);
pn1.add(btn3);
pn1.add(btn4);
//パネルを追加
cp.add(pn1, BorderLayout.SOUTH);
//データ表示
prefDisplay();
}
public void actionPerformed (ActionEvent e) {
Object obj = e.getSource();
if (obj == btn1 || obj == mi1) {
prefInsert();
}else if (obj == btn2 || obj == mi2) {
prefUpdate();
}else if (obj == btn3 || obj == mi3) {
prefDelete();
}else if (obj == btn4 || obj == mi4) {
showExitDialog();
}else if (obj == mi5) {
prefSearch();
}else if (obj == mi6) {
}
}
public void valueChanged (ListSelectionEvent e) {
String str = (String)lt.getSelectedValue();
StringTokenizer st = new StringTokenizer(str, ",");
int arraySize = st.countTokens();
tkn = new String[arraySize];
int i = 0;
while(st.hasMoreTokens()) {
tkn[i] = st.nextToken();
i++;
}
lb1.setText("PREF_CD:" + tkn[0] + " PREF_NAME:" + tkn[1]);
}
private void prefDisplay () {
try {
//データベースに接続
Connection con = SampleDb030.getConnection();
//ステートメントオブジェクトを作成
Statement stmt = con.createStatement();
//SQL文作成
String mySql = "select * from T01Prefecture order by PREF_CD";
//検索するSQL実行
ResultSet rs = stmt.executeQuery(mySql);
ArrayList<String> listData = new ArrayList<String>();
//結果セットからデータを取り出す next()で次の行に移動
while(rs.next()) {
int prefCd = rs.getInt("PREF_CD");
String prefName = rs.getString("PREF_NAME");
listData.add(prefCd + "," + prefName);
}
lt.setListData(listData.toArray());
//オブジェクトを解放
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
System.out.println("例外発生:" + e );
}
}
private void showExitDialog () {
//終了ダイアログボックスの表示
int ret = JOptionPane.showConfirmDialog (cp, "プログラムを終了しますか?", "確認", JOptionPane.YES_NO_OPTION);
if(ret == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
private void prefInsert () {
//追加
String message = "PREF_CD を入力してください。";
String title = "追加";
String prefCd = JOptionPane.showInputDialog (cp, message, title,JOptionPane.QUESTION_MESSAGE);
if(prefCd != null && !prefCd.equals("")) {
String message2 = "PREF_NAME を入力してください。";
String prefName = JOptionPane.showInputDialog (cp, message2, title,JOptionPane.QUESTION_MESSAGE);
if(prefName != null && !prefName.equals("")) {
String mySql = "insert into T01Prefecture values(" + prefCd + ", '" + prefName + "')";
System.out.println(mySql);
}
}
}
private void prefUpdate () {
//更新
String prefCd = (tkn != null) ? tkn[0] : null;
String prefName = (tkn != null) ? tkn[1] : null;
Object nameObj = null;
if(prefCd != null) {
String message = "「" + prefCd + " " + prefName + "」の\n新しい PREF_NAME を入力してください。";
String title = "更新";
nameObj = JOptionPane.showInputDialog (cp, message, title,JOptionPane.QUESTION_MESSAGE, null, null, prefName);
}else{
JOptionPane.showMessageDialog(cp, "先に都道府県を選択してください。");
}
if(nameObj != null) {
prefName = (String)nameObj;
String mySql = "update T01Prefecture set PREF_NAME = '" + prefName + "' where PREF_CD = " + prefCd;
System.out.println(mySql);
}
}
private void prefDelete () {
//削除
String prefCd = (tkn != null) ? tkn[0] : null;
String prefName = (tkn != null) ? tkn[1] : null;
int ret = -9;
if(prefCd != null) {
String message = "「" + prefCd + " " + prefName + "」を削除しますか?";
String title = "削除";
ret = JOptionPane.showConfirmDialog (cp, message, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
}else{
JOptionPane.showMessageDialog(cp, "先に都道府県を選択してください。");
}
if(ret == JOptionPane.OK_OPTION) {
String mySql = "delete from T01Prefecture where PREF_CD = " + prefCd;
System.out.println(mySql);
}
}
private void prefSearch () {
//検索
String message = "PREF_NAME の一部を入力してください。";
String title = "検索";
String prefName = JOptionPane.showInputDialog (cp, message, title, JOptionPane.QUESTION_MESSAGE);
if(prefName != null && !prefName.equals("")) {
String mySql = "select * from T01Prefecture where PREF_NAME like '%" + prefName + "%'";
System.out.println(mySql);
}
}
}
public class PrefTest {
public static void main(String args[]) {
PrefFrame frm = new PrefFrame("都道府県マスター");
//フレームの設定
frm.setLocation(300, 200);
frm.setSize(250, 350);
frm.cp.setBackground(Color.LIGHT_GRAY);
frm.setVisible(true);
}
}
【4】コマンドプロンプトを起動して、カレントディレクトリを sample215 に切り替えます。
【5】javac PrefTest.java と入力し、コンパイルします。
【6】java PrefTest と入力し、プログラムを実行します。
【7】都道府県マスターが表示されました。
【8】「追加」ボタンをクリックします。
【9】PREF_CD を入力するダイアログボックスが表示されました。
【10】99 と入力します。
【11】「了解」ボタンをクリックします。
【12】次に PREF_NAME を入力するダイアログボックスが表示されました。
【13】ハワイ と入力します。
【14】「了解」ボタンをクリックします。
【15】コマンドプロンプトに追加のSQL文が表示されました。
*SQL文が表示されるだけで、データベースに変化はありません。安心してどんどん試してください。
【16】まだリストの都道府県は選択せずに、「更新」ボタンをクリックします。もし都道府県を選択してしまっている場合は、一度プログラムを終了して再度実行してください。
【17】都道府県を選択していない場合は、メッセージが表示されることを確認して、「了解」ボタンをクリックします。
【18】今度は都道府県を選択してから、「更新」ボタンをクリックします。
【19】更新するダイアログボックスが表示されました。リストから選択した都道府県が対象になり、初期値としてデータが入力された状態です。
【20】 PREF_NAME を グアム に変更します。
【21】「了解」ボタンをクリックします。
【22】コマンドプロンプトに更新のSQL文が表示されました。
【23】都道府県を選択してから、「削除」ボタンをクリックします。
【24】削除するダイアログボックスが表示されました。リストから選択した都道府県が対象になっています。
【25】「了解」ボタンをクリックします。
【26】コマンドプロンプトに削除のSQL文が表示されました。
【27】メニューから「検索」を選択します。
【28】検索するダイアログボックスが表示されました。
【29】長 と入力します。
【30】「了解」ボタンをクリックします。
【31】コマンドプロンプトに検索のSQL文が表示されました。
【32】メニューから「追加」、「更新」、「削除」を選択して、同じように動作するか確認してください。
【33】それぞれのダイアログボックスで、「取消し」ボタンをクリックしたときの動きも確認してください。
【解説】
(1)リストで選択した値を保持するための配列 tkn は、他のメソッドでも利用するため、フィールド変数として、メソッドの外で宣言するようにしました。(クラスの最初のほうに移動しました)
String[] tkn;
(2)actionPerformed() メソッドでは、各ボタンやメニューがクリックされた時に、実際に処理を行う他のメソッドを呼び出しています。これにより actionPerformed() メソッド自体はシンプルになっています。
public void actionPerformed (ActionEvent e) {
Object obj = e.getSource();
if (obj == btn1 || obj == mi1) {
prefInsert();
}else if (obj == btn2 || obj == mi2) {
prefUpdate();
}else if (obj == btn3 || obj == mi3) {
prefDelete();
}else if (obj == btn4 || obj == mi4) {
showExitDialog();
}else if (obj == mi5) {
prefSearch();
}else if (obj == mi6) {
}
}
(3)ダイアログボックスの表示には javax.swing パッケージの JOptionPane クラスを使っています。詳細は Java の API 仕様をご覧ください。
・ダイアログボックスを表示するためのメソッド
showConfirmDialog Yes、No、Cancel などの確認に使う
showInputDialog ユーザーからの入力に使う
showMessageDialog ユーザへのメッセージに使う
showOptionDialog 上記を組み合わせたもの 今回は未使用
これらは static メソッドなのでインスタンスを生成しなくても「クラス名.メソッド名」で使えます。引数の型や数で同じ名前のメソッドが複数ありますので注意して使ってください。
・引数の意味
parentComponent ダイアログボックスの親コンポーネント
message ダイアログボックスに表示するメッセージ
title ダイアログボックスのタイトル
optionType ダイアログボックスのボタン
messageType メッセージアイコン
initialValue デフォルトの入力値
・optionTypeに使用可能な値
DEFAULT_OPTION
YES_NO_OPTION
YES_NO_CANCEL_OPTION
OK_CANCEL_OPTION
・messageTypeに使用可能な値
ERROR_MESSAGE
INFORMATION_MESSAGE
WARNING_MESSAGE
QUESTION_MESSAGE
PLAIN_MESSAGE
・showConfirmDialog()メソッドが整数を返した場合の値
YES_OPTION 0
NO_OPTION 1
CANCEL_OPTION 2
OK_OPTION 0
CLOSED_OPTION -1
(4)showInputDialog からの戻り値について
ダイアログボックスのボタンをクリックしたときの戻り値には注意が必要です。
・「取消し」ボタンをクリック → null
・データ未入力で「了解」ボタンをクリック → "" 空白文字列
・データ入力で「了解」ボタンをクリック → 文字列
上記までの基本をふまえて各メソッドを見てみましょう。
(5)prefInsert()メソッド
・使っているメソッド
static String showInputDialog(Component parentComponent, Object message, String title, int messageType)
・新規に追加する PREF_CD をダイアログボックスから入力します。ダイアログボックスの戻り値は String 型です。
・messageは 一般的に String型 で指定しますが、実際には Object 型です。
・PREF_CD のダイアログボックスで、取消しボタンをクリックした場合ではなく、かつ未入力でも無いときに PREF_NAME のダイアログボックスを表示します。
if(prefCd != null && !prefCd.equals("")) {
・PREF_NAME のダイアログボックスで、取消しボタンをクリックした場合ではなく、かつ未入力でも無いときにSQL文を作成しています。
if(prefName != null && !prefName.equals("")) {
つまり、PREF_CD と PREF_NAME の両方が入力されていないと、SQL文は作成されないようにしています。
本来ならダイアログボックスに入力された値が適切かどうか、チェックする必要があります。PREF_CDに数値に変換できない文字が入力されていたり、PREF_NAMEにSQL文に影響がある特別な意味をもつ文字が入力された場合などです。しかし今回は大きな流れをつかんでほしいため省略しています。
*SQL文については、Access SQL初心者入門講座で詳しく解説しています。
(6)prefUpdate()メソッド
・使っているメソッド
static Object showInputDialog(Component parentComponent, Object message, String title, int messageType, Icon icon, Object[] selectionValues, Object initialSelectionValue)
・リストで選択した値をもとにダイアログボックスを表示しています。デフォルトの入力値は選択した都道府県です。ダイアログボックスからの戻り値が Object 型であることに注意してください。
・リストを選択した時には、配列 tkn に切り出したデータの参照が入っています。それを三項演算子(条件演算子)でデータが null でない場合は代入、それ以外なら null で変数を初期化しています。三項演算子は if 文に似た制御ができ、また結果の値を返すこともできます。
=(式)? 真:偽 値を返したいとき
String prefCd = (tkn != null) ? tkn[0] : null;
String prefName = (tkn != null) ? tkn[1] : null;
・PREF_NAMEが入力された場合に、String型に変換してSQL文を作成しています。更新では空白文字はOKとしました。
if(nameObj != null) {
prefName = (String)nameObj;
(7)prefDelete()メソッド
・使っているメソッド
static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType)
・ボタンの戻り値に使われていない値で初期化しています。-1,0,1,2以外なら何でもかまいません。
int ret = -9;
・削除確認のメッセージを表示して、「了解」ボタンをクリックした場合にSQL文を作成しています。OK_OPTION は 0 でしたね。0 == 0 ならという意味になります。
if(ret == JOptionPane.OK_OPTION) {
(8)prefSearch()メソッド
・使っているメソッド
static String showInputDialog(Component parentComponent, Object message, String title, int messageType)
・検索する文字列を入力するためのダイアログボックスを表示します。ダイアログボックスで取消しボタンをクリックした場合ではなく、かつ未入力でも無いときにSQL文を作成しています。
if(prefName != null && !prefName.equals("")) {
String mySql = "select * from T01Prefecture where PREF_NAME like '%" + prefName + "%'";
*Accessではあいまい検索に「*」アスタリスクを使いますが、「%」パーセントを使っている点に注意してください。
【ワンポイント】
変数の値を確認するのに、コマンドプロンプトを使うのは便利ですので覚えておいてください。他にもラベルに表示する手もあります。
もっとも Eclipse のような統合開発環境を使えば、プログラムの実行中に変数の変化を簡単に確認することができます。しかもメソッドがどんな例外を発生する可能性があるのか教えてくれたり、try-catch文で囲んでくれたりするので、プログラミングが楽になります。
もう少しで Eclipse での製作に入りますので、それまでは頑張ってください。