広告 |
---|
■□■□■□■□■□■□■□■□■□■□■□■□■□■□■ 2011年12月19日 Java総合講座 - 初心者から達人へのパスポート 2009年11月開講コース 051号 セルゲイ・ランダウ バックナンバー: http://www.flsi.co.jp/Java_text/ ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■ ------------------------------------------------------- ・現在、このメールマガジンは以下の2部構成になっています。 [1] 当初からのコース:vol.xxx(xxxは番号)が振られています。 これは現在、中級レベルになっています。 [2] 2009年11月開講コース:xxx号(xxxは番号)が振られています。 これは現在、初心者向けのレベルになっています。 ・このメールマガジンは、画面を最大化して見てください。 小さな画面で見ていると、不適切な位置で行が切れてしまう など、問題を起すことがあります。 ・このメールマガジンに掲載されているソース・コード及び 文章は特に断らない限り、すべて筆者が著作権を所有してい ます。また、これらのソース・コードは学習用のためだけに 提供しているものです。 ------------------------------------------------------- ======================================================== ◆ 01.データベースを使用するアプリケーションの開発(続き) ======================================================== 今回は、HumanResourceEntryPaneに「削除」の機能を組み込み ます。 これまでの記事で、データベースを使用するアプリケーションの 作り方のパターンはだいたい理解できたことと思いますので、 今回は説明をごく簡単に済ませることにします。 では、まず最初に例によって、EmployeeDbManagerクラスにデータ の削除のメソッドを追加しましょう EclipseでEmployeeDbManagerのエディターを開き、以下の編集を 行ってください。 まず、下記のPreparedStatement型の変数 -------------------------------------------------------- private String deleteSql = "DELETE FROM EMPLOYEE WHERE EMP_NUM = ?"; -------------------------------------------------------- を追加しましょう。 次に、下記のメソッドを追加しましょう。 -------------------------------------------------------- public boolean deleteData(Employee anEmployee) { try { connect(); PreparedStatement selectPs = conn.prepareStatement(selectSql); selectPs.setInt(1, anEmployee.getEmployeeNumber()); ResultSet rs = selectPs.executeQuery(); if (!rs.next()) return false; selectPs.close(); conn.setAutoCommit(false); PreparedStatement deletePs = conn.prepareStatement(deleteSql); deletePs.setInt(1, anEmployee.getEmployeeNumber()); deletePs.executeUpdate(); deletePs.close(); conn.commit(); disconnect(); } catch (SQLException exception) { exception.printStackTrace(); } return true; } -------------------------------------------------------- このソース・コードでは、例によって、該当する社員番号がデータ ベース上に存在することを確認した上で、その社員のデータを削除 しています。 これもソース・コードの説明はもう必要ないですね では、続いてHumanResourceEntryPane側の編集を行いましょう。 これまでは、「新規登録」のページ、「検索」のページ、「更新」の ページというように各機能ごとに専用のページを用意していましたが、 今回は作業を簡単に済ませるために「更新」のページに「削除」の ボタンを付け足し、「更新」のページに表示されている社員番号に対し て「削除」を実行するようにします。 HumanResourceEntryPaneのエディター(WindowBuilder Editor)を開い て、Designビューで「更新」のページを表示してください。 Palette(パレット)のComponents配下からJButtonを選択し、 「更新」ボタンの右側に貼り付けましょう。 変数名(Properties欄のVariable)は「jButtonDelete」にしましょう。 また、textプロパティーの値は「削除」にしましょう。 次に、この「削除」ボタンを右クリックし、「Add event handler」→ 「アクション」→「actionPerformed」を選択します。 そうすると、getJButtonDelete()メソッドの中に下記のソース・コード が自動生成されますね。 -------------------------------------------------------- jButtonDelete.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { } }); -------------------------------------------------------- これを下記のように編集しましょう。 -------------------------------------------------------- jButtonDelete.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Employee anEmployee = new Employee(); int empNumber; try { empNumber = Integer.parseInt(getJTextFieldEmpNum().getText()); } catch (NumberFormatException e1) { getMessageDialog().getTextPane().setText("エラー:社員番号の入力値が数字になっていません。"); getMessageDialog().setVisible(true); return; } anEmployee.setEmployeeNumber(empNumber); EmployeeDbManager empDbManager = new EmployeeDbManager(); if (empDbManager.deleteData(anEmployee)) { getMessageDialog().getTextPane().setText("削除が完了しました。"); getMessageDialog().setVisible(true); } else { getMessageDialog().getTextPane().setText("指定された社員番号が存在しないため、削除はできませんでした。"); getMessageDialog().setVisible(true); } } }); -------------------------------------------------------- このソース・コードも、もう説明不要ですね。 ところで、このHumanResourceEntryPaneのソース・コードの中には、やたらに -------------------------------------------------------- getMessageDialog().getTextPane().setText("○○○"); getMessageDialog().setVisible(true); -------------------------------------------------------- の組み合わせが何度も出てきますね。 この組み合わせはメソッド化してしまって、メッセージの部分(上記の"○○○" の部分)のような可変部分はメソッドの引数で受け渡しする形にすれば、それぞれ の2行の部分が1行のメソッド呼び出しに置き換えることができ、ソース・コード の行数が減ってすっきりするし、間違いも減る(たとえばsetVisible(true)の呼び 出しは書き忘れやすいが、それを忘れる心配がなくなる)と感じた人もいることで しょう。 (ここではgetMessageDialog()によってMessageDialogのインスタンスを呼び出して そのメソッドを使っているわけですが、MessageDialogのような汎用性のあるクラスは、 後で他のアプリケーションでも再利用される可能性が高いですが、その場合に上記の 2行のような余計なコードをいちいち書かされるのでは不便です。やはり一つのメソッド にしてしまったほうがよいでしょう。) というわけで、上記の2行をメソッド化する作業をやってみましょう。 ちなみに、これも一種のリファクタリングですが、(プロであれば2〜3分でできる) 簡単な作業なので、今回は最初から手作業で行います。 まず、(jp.co.flsi.lecture.uiパッケージの)MessageDialog.javaのソース・コード をエディターで開きましょう。 (1) このクラスに下記のようなメソッドを追加しましょう。 -------------------------------------------------------- public void setMessageAndShow(String message) { getTextPane().setText(message); setVisible(true); } -------------------------------------------------------- (2) 上記のメソッドを使えば、getTextPane()メソッドを公開する必要はなく なるので、getTextPane()メソッドはprivateに変更します。つまり、 getTextPane()メソッドを定義しているコードを下記のように書き換えます。 (コードの場所を見つけにくい場合は、以前お話したようにgetTextPaneの 文字列の中にカーソルを入れてF3キーを押せば、そのメソッドの定義の所 に飛んでくれます。) -------------------------------------------------------- private JTextPane getTextPane() { return textPane; } -------------------------------------------------------- (変更するのはpublicをprivateに書き換えることだけです。) (3) すると、HumanResourceEntryPaneのソース・コードの中で上のgetTextPane() を呼び出していた所がことごとくエラー(赤いアンダーラインが付く)になり ますね。(これで、書き換えるべき所が一目瞭然になります。) そこをことごとく上のsetMessageAndShow()メソッドの呼び出しに 書き換えます。つまり、getButton()メソッド、getJButtonUpdate()メソッド、 getJButtonDelete()メソッドの定義のコードをそれぞれ下記のように書き換え ます。これは「getTextPane().setText」の文字列を置換の機能(メニュー・バー から「編集」→「検索/置換」を選択)で「setMessageAndShow」に一挙に変換 すれば簡単にできます。ただし、その後 getMessageDialog().setVisible(true); の行をことごとく削除するのを忘れないように(これも置換の機能で一挙に 空白行に変換すれば簡単である)。 -------------------------------------------------------- private JButton getButton() { if (button == null) { button = new JButton("\u767B\u9332"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Employee anEmployee = new Employee(); int empNumber; try { empNumber = Integer.parseInt(getJTextFieldEntryEmpNum().getText()); } catch (NumberFormatException e1) { String errorHtml = "<HTML>" + "<HEAD><TITLE>エラー・メッセージ</TITLE></HEAD>" + "<BODY>" + "<FONT color=\"FF0000\" size=\"+1\">エラー:</FONT><BR>" + "<FONT color=\"0000FF\">社員番号</FONT>の入力値が数字になっていません。" + "</BODY>" + "</HTML>"; getMessageDialog().setMessageAndShow(errorHtml); return; } anEmployee.setEmployeeNumber(empNumber); anEmployee.setName(getJTextFieldEntryName().getText()); CalendarConverter aCalConverter = new CalendarConverter(); aCalConverter.setDay(Integer.parseInt(getTextField().getText())); aCalConverter.setMonth(Integer.parseInt(getTextField_1().getText())); aCalConverter.setJaNameOfEra(getComboBox().getSelectedIndex()); switch (aCalConverter.getJaNameOfEra()) { case 0: case 1: case 2: case 3: aCalConverter.setJaYear(Integer.parseInt(getJTextField2().getText())); aCalConverter.convertJaCal2GreCal(); break; default: aCalConverter.setGreYear(Integer.parseInt(getJTextField2().getText())); break; } anEmployee.setDateOfBirth(aCalConverter.getGreYear(), aCalConverter.getMonth(), aCalConverter.getDay()); ComboBoxModelOfDepartment aBoxModelOfDepartment = (ComboBoxModelOfDepartment) getComboBox_1().getModel(); Department aDepartment = (Department)aBoxModelOfDepartment.getDepartmentList().get(getComboBox_1().getSelectedIndex()); anEmployee.setDepartmentNumber(aDepartment.getDepartmentNumber()); EmployeeDbManager empDbManager = new EmployeeDbManager(); if (empDbManager.insertData(anEmployee)) { getMessageDialog().setMessageAndShow("新規登録が完了しました。"); } else { getMessageDialog().setMessageAndShow("指定された社員番号がすでに存在するため、新規登録はできませんでした。"); } } }); } return button; } -------------------------------------------------------- -------------------------------------------------------- private JButton getJButtonUpdate() { if (jButtonUpdate == null) { jButtonUpdate = new JButton("\u66F4\u65B0"); jButtonUpdate.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Employee anEmployee = new Employee(); int empNumber; try { empNumber = Integer.parseInt(getJTextFieldEmpNum().getText()); } catch (NumberFormatException e1) { getMessageDialog().setMessageAndShow("エラー:社員番号の入力値が数字になっていません。"); return; } anEmployee.setEmployeeNumber(empNumber); anEmployee.setName(getJTextFieldName().getText()); CalendarConverter aCalConverter = new CalendarConverter(); aCalConverter.setDay(Integer.parseInt(getJTextFieldDay().getText())); aCalConverter.setMonth(Integer.parseInt(getJTextFieldMonth().getText())); aCalConverter.setJaNameOfEra(getJComboBoxEra().getSelectedIndex()); switch (aCalConverter.getJaNameOfEra()) { case 0: case 1: case 2: case 3: aCalConverter.setJaYear(Integer.parseInt(getJTextFieldYear().getText())); aCalConverter.convertJaCal2GreCal(); break; default: aCalConverter.setGreYear(Integer.parseInt(getJTextFieldYear().getText())); break; } anEmployee.setDateOfBirth(aCalConverter.getGreYear(), aCalConverter.getMonth(), aCalConverter.getDay()); ComboBoxModelOfDepartment aBoxModelOfDepartment = (ComboBoxModelOfDepartment) getJComboBoxDepart().getModel(); Department aDepartment = (Department)aBoxModelOfDepartment.getDepartmentList().get(getJComboBoxDepart().getSelectedIndex()); anEmployee.setDepartmentNumber(aDepartment.getDepartmentNumber()); EmployeeDbManager empDbManager = new EmployeeDbManager(); if (empDbManager.updateData(anEmployee)) { getMessageDialog().setMessageAndShow("更新が完了しました。"); } else { getMessageDialog().setMessageAndShow("指定された社員番号が存在しないため、更新はできませんでした。"); } } }); } return jButtonUpdate; } -------------------------------------------------------- -------------------------------------------------------- private JButton getJButtonDelete() { if (jButtonDelete == null) { jButtonDelete = new JButton("\u524A\u9664"); jButtonDelete.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Employee anEmployee = new Employee(); int empNumber; try { empNumber = Integer.parseInt(getJTextFieldEmpNum().getText()); } catch (NumberFormatException e1) { getMessageDialog().setMessageAndShow("エラー:社員番号の入力値が数字になっていません。"); return; } anEmployee.setEmployeeNumber(empNumber); EmployeeDbManager empDbManager = new EmployeeDbManager(); if (empDbManager.deleteData(anEmployee)) { getMessageDialog().setMessageAndShow("削除が完了しました。"); } else { getMessageDialog().setMessageAndShow("指定された社員番号が存在しないため、削除はできませんでした。"); } } }); } return jButtonDelete; } -------------------------------------------------------- 編集が終わったらテスト(HumanResourceJFrameの実行)をしてみ ましょう。 これで「人事情報を管理するためのアプリケーション」の基本的な 機能は完成しました。 しかし、このままだと、このアプリケーションは誰でも使えてしまい ますね。 これでは、まずいですから、決められた人(人事管理者)だけしか使 えないようにパスワードで保護することにしましょう。 これは次回やります。 では、今回はここまで。 (続く) ======================================================== ◆ 02.文法解説 [break文] ======================================================== [break文] ループを途中で抜け出したいとき、つまり、ループの実行を途中で やめたいときに使うのが、break文 break; です。 ループが入れ子になって階層構造になっているときは、直近のループ から抜け出すことになります。 たとえば、 -------------------------------------------------------- int i; do { i = (int) (Math.random() * 100); System.out.println("ここ掘れワンワン。掘ったら小判が" + i + "枚。"); for (int j = 1; j < 10; j++) { i -= 10 * j; if (i < 10) { break; } System.out.println(10 * j + "枚使って、残りは" + i + "枚。"); } System.out.println("(forループ終わり)"); } while (i != 5); System.out.println("(doループ終わり)"); -------------------------------------------------------- とすると、このbreak文では、forループを抜け出して、その下の System.out.println("(forループ終わり)"); の行に飛ぶことになります。 ┌補足─────────────────────────┐ 上のソース・コードの中のMathクラスは、数学関連のメソッドを 持つクラスです。 そのうちのrandom()メソッドは、乱数を返すメソッドで、0以上1未満 のdouble型の数値を返します。 なお、random()メソッドはstaticメソッドなので、Math.random()と いう形式で呼び出すことができます。 上のソース・コードの中の i = (int) (Math.random() * 100); では、random()メソッドによって取り出した乱数を100倍した後、 int型にキャストしていますから、0から99までの数がiに代入される ことになります。(乱数ですから無作為な値が出てきます。) └───────────────────────────┘ 複数のループが入れ子になっているとき、すなわち複数のループに よって階層構造になっているときに、どの階層を抜け出したいのか を明示したい場合は、 break ラベル名; という形式で指定します。 このラベル名というのは、 -------------------------------------------------------- ラベル名: { } -------------------------------------------------------- という形式でブロック({と}で囲まれた部分)に名前をつけておいた ものです。 「break ラベル名;」によって、このブロックの外に抜け出ることが できます。 たとえば、 -------------------------------------------------------- int i = 0; outerLoop: { do { i = (int) (Math.random() * 100); System.out.println("ここ掘れワンワン。掘ったら小判が" + i + "枚。"); innerLoop: { for (int j = 1; j < 10; j++) { i -= 10 * j; if (i < 10) { if (i == 5) { System.out.println("(forループ終わり)"); break outerLoop; } else { break innerLoop; } } System.out.println(10 * j + "枚使って、残りは" + i + "枚。"); } } System.out.println("(forループ終わり)"); } while (true); // System.out.println("(ここは実行されない)"); } System.out.println("(doループ終わり)"); -------------------------------------------------------- とすると、 break outerLoop; では、outerLoopのブロックを抜け出しますので、doループの外に 出ます。 また、 break innerLoop; では、innerLoopのブロックを抜け出しますので、forループの外に 出ます。 なお、上のソース・コードのようにwhile (true)を指定した場合には、 いつまでもループの処理を繰り返す、いわゆる「無限ループ」になり ます。 無限ループはどこかの時点で終わらせなければなりませんから、 上のソース・コードのようにbreak文を使って終わらせたりします。 (return文を使ってメソッドごと終わらせる場合もあります。) (続く) ================================================ ◆ 03.演習問題 ================================================ 上記のbreak文の振る舞いを確認するために、下記のようなプロ グラムを作って実行してみてください。 そして、自分で理解している通りの結果が出ることを確認して ください。 -------------------------------------------------------- public class BreakTest { public static void main(String[] args) { System.out.println("[Example 1]"); int i; do { i = (int) (Math.random() * 100); System.out.println("ここ掘れワンワン。掘ったら小判が" + i + "枚。"); for (int j = 1; j < 10; j++) { i -= 10 * j; if (i < 10) { break; } System.out.println(10 * j + "枚使って、残りは" + i + "枚。"); } System.out.println("(forループ終わり)"); } while (i != 5); System.out.println("(doループ終わり)"); System.out.println("\n[Example 2]"); outerLoop: { do { i = (int) (Math.random() * 100); System.out.println("ここ掘れワンワン。掘ったら小判が" + i + "枚。"); innerLoop: { for (int j = 1; j < 10; j++) { i -= 10 * j; if (i < 10) { if (i == 5) { System.out.println("(forループ終わり)"); break outerLoop; } else { break innerLoop; } } System.out.println(10 * j + "枚使って、残りは" + i + "枚。"); } } System.out.println("(forループ終わり)"); } while (true); // System.out.println("(ここは実行されない)"); } System.out.println("(doループ終わり)"); } } -------------------------------------------------------- なお、 // System.out.println("(ここは実行されない)"); の行のコメントをはずす(//のマークを取り除くこと)とどうな るかも確認してみてください。 (次回に続く。) ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ★ホームページ: http://www.flsi.co.jp/Java_text/ ★このメールマガジンは 「まぐまぐ(http://www.mag2.com)」 を利用して発行しています。 ★バックナンバーは http://www.flsi.co.jp/Java_text/ にあります。 ★このメールマガジンの登録/解除は下記Webページでできます。 http://www.mag2.com/m/0000193915.html ★このメールマガジンへの質問は下記Webページにて受け付けて います。わからない所がありましたら、どしどしと質問をお寄 せください。 http://www.flsi.co.jp/Java_text/ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ Copyright (C) 2011 Future Lifestyle Inc. 不許無断複製 |