広告

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■
                      2011年03月01日

    Java総合講座 - 初心者から達人へのパスポート
                  2009年11月開講コース 041号

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■□■□■□■□■□■□■□■□■□■□■□■□■□■□■


-------------------------------------------------------
・現在、このメールマガジンは以下の2部構成になっています。
[1] 当初からのコース:vol.xxx(xxxは番号)が振られています。
   これは現在、中級レベルになっています。
[2] 2009年11月開講コース:xxx号(xxxは番号)が振られています。
   これは現在、初心者向けのレベルになっています。
・このメールマガジンは、画面を最大化して見てください。
小さな画面で見ていると、不適切な位置で行が切れてしまう
など、問題を起すことがあります。
・このメールマガジンに掲載されているソース・コード及び
文章は特に断らない限り、すべて筆者が著作権を所有してい
ます。また、これらのソース・コードは学習用のためだけに
提供しているものです。
-------------------------------------------------------


========================================================
◆ 01.データベースを使用するアプリケーションの開発(続き)
========================================================

前回は、HumanResourceEntryPaneの「登録」ボタンをクリックし
たときの処理内容を記述すべく、getButton()メソッドの中に

--------------------------------------------------------
         button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            }
         });
--------------------------------------------------------

というソース・コードを自動挿入させたところで終わりました。

この自動挿入されたソース・コードの中のactionPerformed()メ
ソッドの中に、実際に実行したいコードを書き込む必要があった
のでしたね。


実際に実行したいのは、HumanResourceEntryPane上の各JTextField
に入力された値やJComboBoxで選択された値を使ってEMPLOYEEテー
ブルに追加するデータを作成し、データベースに書き込む、という
操作です。

さて、この操作のコーディングを行う前に、EMPLOYEEテーブルに
対応するクラスとしてEmployeeというクラスを用意しておきま
しょう。
Employeeクラスはいうまでもなく社員を表現するクラスです。

Employeeクラスには社員番号(employeeNumber)、氏名(name)、
生年月日(dateOfBirth)、所属部署コード(departmentNumber)
の属性を持たせ、EmployeeクラスとEMPLOYEEテーブルの間には以下
のような対応付け(マッピング)を行います。

Employeeクラス          EMPLOYEEテーブル
 の属性             のカラム
========        =========
employeeNumber       <-->    EMP_NUM
name                 <-->    NAME
dateOfBirth          <-->    DATE_OF_BIRTH
departmentNumber     <-->    DEPART_NUM


では、Eclipseを使ってEmployeeクラスを作っていきましょう。

┌───────────────────────────┐
     Employeeクラスの作成
└───────────────────────────┘

(1) パッケージ・エクスプローラーの中のjp.co.flsi.lecture.entity
(パッケージ)を右クリックし、「新規」→「クラス」を選択します。

(2) 「新規Javaクラス」ウインドウで「ソース・フォルダー」の欄
に「JStudy1/src」がはいっていることを確認し、「パッケージ」の
欄に「jp.co.flsi.lecture.entity」がはいっていることを確認し、
「名前」の欄に
Employee
と入力します。

(なお、「どのメソッド・スタブを作成しますか?」の
「public static void main(String[] args)」や
「スーパークラスからのコンストラクター」にはチェックマークは
入れないでください。)

(3) 「完了」ボタンをクリックします。

そうすると、Employeeのエディターが開きますので、Employeeの
各属性を記述するフィールドを定義するコードを入力しましょう。
下記にソース・コードの例を提示します。

--------------------------------------------------------
package jp.co.flsi.lecture.entity;

import java.util.GregorianCalendar;

public class Employee {
   private int employeeNumber;
   private String name;
   private GregorianCalendar dateOfBirth;
   private int departmentNumber;
}
--------------------------------------------------------

次に、各フィールドのsetメソッド(setter)、getメソッド(getter)
を作成します。生産性を上げるために以下のようにリファクタリングの
機能を利用して作成しましょう。

(1) Employeeのエディターのソース・コード内のemployeeNumberの部分
をクリックし、右クリック→「リファクタリング」→「フィールドのカプセル化」
を選択します。
(上記の操作の代わりに、employeeNumberの部分をクリックし、Alt+Shift+T
キーを押し、「フィールドのカプセル化」を選択してもよい。)

(2) 「フィールドのカプセル化」ウインドウにおいて、「アクセス修飾子」
は「public」を選択し、「宣言型でのフィールド・アクセス」は「setter
とgetterの使用」を選択し(これがデフォルト)、「OK」ボタンをクリッ
クします。
そうすると、employeeNumberのsetメソッド(setter)、getメソッド
(getter)のソース・コードが自動生成されます。

(3) 同様にEmployeeのエディターのソース・コード内のnameの部分を
クリックし、右クリック(またはAlt+Shift+T)→「リファクタリング」
→「フィールドのカプセル化」を選択します。

(4) 「フィールドのカプセル化」ウインドウにおいて、「アクセス修飾子」
は「public」を選択し、「宣言型でのフィールド・アクセス」は「setter
とgetterの使用」を選択し(これがデフォルト)、「OK」ボタンをクリッ
クします。
そうすると、nameのsetメソッド、getメソッドのソース・コードが自動
生成されます。

(5) 以下、dateOfBirthとdepartmentNumberについても上記と同様の操作
を行うことによって、setメソッド、getメソッドを作成します。

(ソース・コードの字下げ(インデント)をきれいに揃えたいときは、
Ctrl+Aで全ソース・コードを選択してから、Ctrl+Iでインデントを
揃える。)


ところで、このクラスでは生年月日のフィールド(dateOfBirth)の型
をGregorianCalendarにしていますが、HumanResourceEntryPaneの画面上
では、生年月日は年と月と日をそれぞれ別々の数字として入力するよう
にしています。

したがって、これら年と月と日の3種類の数値からGregorianCalendar型
の値を構築するためのsetメソッドも用意しておくことにします。
下記のようなソース・コードを入力しておきましょう。

--------------------------------------------------------
public void setDateOfBirth(int birthYear, int birthMonth, int birthDate) {
   dateOfBirth = new GregorianCalendar(birthYear, birthMonth -1, birthDate);
}
--------------------------------------------------------

このsetDateOfBirth()メソッドは引数に指定した年(birthYear)、
月(birthMonth)、日(birthMonth)からGregorianCalendar型の
インスタンスを生成するものですが、

dateOfBirth = new GregorianCalendar(birthYear, birthMonth -1, birthDate);

というコードの意味については既にvol.007で説明しました。

このsetDateOfBirth()メソッドも含めたEmployeeクラスの全体の
ソース・コードを下に提示しておきます。

--------------------------------------------------------
package jp.co.flsi.lecture.entity;

import java.util.GregorianCalendar;

public class Employee {
   private int employeeNumber;
   private String name;
   private GregorianCalendar dateOfBirth;
   private int departmentNumber;
   public void setEmployeeNumber(int employeeNumber) {
      this.employeeNumber = employeeNumber;
   }
   public int getEmployeeNumber() {
      return employeeNumber;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }
   public void setDateOfBirth(GregorianCalendar dateOfBirth) {
      this.dateOfBirth = dateOfBirth;
   }
   public void setDateOfBirth(int birthYear, int birthMonth, int birthDate) {
      dateOfBirth = new GregorianCalendar(birthYear, birthMonth -1, birthDate);
   }
   public GregorianCalendar getDateOfBirth() {
      return dateOfBirth;
   }
   public void setDepartmentNumber(int departmentNumber) {
      this.departmentNumber = departmentNumber;
   }
   public int getDepartmentNumber() {
      return departmentNumber;
   }

}
--------------------------------------------------------


┌補足─────────────────────────┐
 上記のEmployeeクラスではsetDateOfBirth()メソッドが2つ定義
 されています。
 つまり、
 setDateOfBirth(GregorianCalendar dateOfBirth)
 と
 setDateOfBirth(int birthYear, int birthMonth, int birthDate)
 という、メソッド名は同じだが引数の型(あるいは引数の個数)
 が異なるものが2つあります。

 このように引数の型や引数の個数が異なっていれば、同名のメソッ
 ドを複数定義することが許されており、この複数定義を「多重定義」
 または「オーバーロード」(overload)といいます。
 オーバーロードという言葉はオーバーライド(override)と似ていて
 紛らわしいかもしれませんが間違えないで下さい。
└───────────────────────────┘


では、次にこのEmployeeオブジェクトの持つ属性の値をEMPLOYEEテー
ブルに書き出すためのクラスを作成しましょう。
その名もEmployeeDbManagerとし、DepartmentDbManagerの場合と同じく
DbManagerのサブクラスにします。


┌───────────────────────────┐
     EmployeeDbManagerクラスの作成
└───────────────────────────┘

(1) パッケージ・エクスプローラーの中のjp.co.flsi.lecture.db
(パッケージ)を右クリックし、「新規」→「クラス」を選択します。

(2) 「新規Javaクラス」ウインドウで「ソース・フォルダー」の欄
に「JStudy1/src」がはいっていることを確認し、「パッケージ」の
欄に「jp.co.flsi.lecture.db」がはいっていることを確認し、
「名前」の欄に
EmployeeDbManager
と入力します。

(3) 「完了」ボタンをクリックします。

そうすると、EmployeeDbManagerのエディターが開きますので、
EmployeeDbManagerのソース・コードを下記のように
完成させましょう。

--------------------------------------------------------
package jp.co.flsi.lecture.db;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import jp.co.flsi.lecture.entity.Employee;

public class EmployeeDbManager extends DbManager {
   private String selectSql = "SELECT * FROM EMPLOYEE WHERE EMP_NUM = ?";
   private String insertSql = "INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)";

   public boolean insertData(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 insertPs = conn.prepareStatement(insertSql);
         insertPs.setInt(1, anEmployee.getEmployeeNumber());
         insertPs.setString(2, anEmployee.getName());
         insertPs.setDate(3, new java.sql.Date(anEmployee.getDateOfBirth().getTimeInMillis()));
         insertPs.setInt(4, anEmployee.getDepartmentNumber());
         insertPs.executeUpdate();
         insertPs.close();
         conn.commit();
         disconnect();
      }
      catch (SQLException exception) {
         exception.printStackTrace();
      }
      return true;
   }

}
--------------------------------------------------------


はい、では、これでお膳立てが整ったので、HumanResourceEntryPane
のエディターに戻りましょう。

actionPerformed()メソッドの実装の話に戻ります。

念のために現時点のgetButton()メソッドのソース・コードを下に
提示しておきます。

--------------------------------------------------------
   private JButton getButton() {
      if (button == null) {
         button = new JButton("\u767B\u9332");
         button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            }
         });
      }
      return button;
   }
--------------------------------------------------------

このgetButton()メソッドの部分を下記のソース・コードに書き換えてみてください。

--------------------------------------------------------
   private JButton getButton() {
      if (button == null) {
         button = new JButton("\u767B\u9332");
         button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
               Employee anEmployee = new Employee();
               anEmployee.setEmployeeNumber(Integer.parseInt(getJTextField().getText()));
               anEmployee.setName(getJTextField1().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();
               empDbManager.insertData(anEmployee);
            }
         });
      }
      return button;
   }
--------------------------------------------------------

お分かりのことと思いますが、あくまでactionPerformed()メソッド、つまり

            public void actionPerformed(ActionEvent e) {
            }

の中にコードを追加しただけです。


なお、上記のコードをそのまんま入力すると、「Employee」などいくつか
の部分がエラー(赤いアンダーラインがつく)になりますが、コンテンツ・
アシスト(Ctrl + スペース・キー)の機能を使って入力すればimport文が
自動生成されるのでエラーは消えます(039号参照)。


以上のソース・コードの解説は、次回行います。


以上のプログラミングで、とりあえずHumanresourceEntryPaneの「登録」
ボタンは機能するようになったはずですが、まだ何か物足りないところが
あります。

(次回に続く。)


では、また来週。



================================================
◆ 02.演習問題
================================================

1. 上記のソース・コードの入力が一通り終わった段階で、一度
HumanResourceJFrameを実行して、動作確認してみてください。
(なお、予め H2 Consoleを立ち上げるなどしてH2 Database EngineのRDBMSを
起動しておくことを忘れないこと。)

2. 上で最後に「まだ何か物足りないところがあります。」と書いて
あるのは、どういう意味だと思いますか。
自分なりに思いつくことを列挙してみてください。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      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. 不許無断複製