疑似DAOクラスから本物のDAOクラスを作成
上記の説明で、銘柄1つ分に相当するImoshochuCatalogItemのArrayListをDAOクラスとServletのインターフェースとすると、JSPで式言語とJSTLのみでカタログを表示させることができました。残るは疑似的に作成したImoshochuCatalogDaoクラスから実際のデータベースにアクセスするDAOクラスの作るのみとなりました。
筆者の自宅のデータベースはもっぱらMySQLを使用しています。MySQLを使うとなると、MySQLやMySQL GUI ToolsなどのダウンロードやそれらをNetBeansで使用できるようにするための手順を説明しなくてはなりません。悩んでいたところNetBeansの「MySQL データベースへの接続」というページがありました。非常に分かりやすく書かれているため、MySQLとNetBeansの接続は当サイトを参考にしてください。ただし、英語版のNetBeans 6.8をベースとした説明であることや設定すべきものが何か分かるづらいところだけ説明します。
MySQLやMySQL GUI Toolsは先述のサイトを参考にダウンロード・インストールしてください。インストールする際に入力したパスワードなど忘れないようにメモに残しておきましょう。以下にNetBeansにMySQLを接続するための手順を説明します。
サービスウィンドウを開く
通常、NetBeansの左上にプロジェクトウィンドウがあります。ImoshochuWeb01プロジェクトが作成されているウィンドウです。そのペインにファイルやkenaiウィンドウも存在していると思います。もし、サービスウィンドウがない場合、[ウィンドウ]-[サービス]と操作すると先ほどのペインにサービスウィンドウが表示されます。そのウィンドウには「データベース」「Web サービス」「サーバー」「Hudson ビルダ」「課題追跡」が表示されているはずです。この中の[データベース]を右クリックし[MySQL サーバーを登録]を選択します。[MySQL サーバープロパティー]画面が表示されます。
基本プロパティーを設定
[基本プロパティー]タブを選択すると図16のような画面が表示されます。各設定内容は以下の通りです。
- サーバーホスト名:ホスト名またはIPアドレスを入力します。IPアドレスの場合は「192.168.1.10」のように入力します。
- サーバーポート番号:MySQLの場合、3306がデフォルトのためそのままにします。
- 管理者のユーザー名:MySQLのインストール時に指定した管理者名を入力します。
- 管理者のパスワード:MySQLのインストール時に指定した管理者のパスワードを入力します。ここでメモしたものが役立ちます。学習する分にはパスワードに「root」や「password」など入力しても構いません。業務で使用する場合もこのようなパスワードを使用しているのを何度も見かけていますが、セキュリティ上絶対避けるべきことのひとつです。データベースのパスワードは企業情報を守る最後の砦です。推測不能なパスワードを入力してください。
管理プロパティーを設定
[基本プロパティー]タブの右隣にある[管理プロパティー]をクリックします。図17が管理プロパティーの設定画面です。各設定内容は以下の通りです。
- 管理ツールのパスまたはURL:MySQL GUI Toolsでダウンロードしたフォルダの中のMySQLWorkbench.exe(Windowsの場合)のパスを指定します。
- 起動コマンドのパス:これはMySQL自体の起動コマンドを指定します。インストールしたフォルダ配下のbinフォルダにあるmysqld.exe(Windowsの場合)を指定します。
- 停止コマンドのパス:これもMySQL自体の停止コマンドを指定します。上記と同じコマンドではなく、mysqladmin.exe(Windowsの場合)のパスを指定します。
- 引数:mysqladmin.exeの場合、停止するには引数が必要となります。「-u root stop」と入力してください
データベースを作成
[MySQL サーバーを登録]を完了するとデータベースの下に「MySQL サーバー localhost:3306 [root]」というノードが生成されているはずです。生成されていれば、MySQLサーバとNetBeansの接続が成功したことになります。
「MySQL サーバー localhost:3306 [root]」を右クリックし[データベースを作成]を選択すると[MySQL データベースの作成]画面が表示されます。新規データベース名に「imoshop」と入力します。「MySQL サーバー localhost:3306 [root]」ノード配下にデフォルトで存在する「information_schema」「mysql」「test」と同じレベルに「imoshop」ができているはずです。MySQL Workbenchを使用するには「MySQL サーバー localhost:3306 [root]」ノードを右クリック、「管理ツールを実行」を選択すると、MySQL Workbenchが起動します。使い方はMySQL Documentation:MySQL Workbenchのサイトを参考にしてください(日本語版が見つかったら追記します)。
meigaraテーブルを作成します。カラムはid(主キー)、name、nameKana、dosu、koji、sweetPotatoName、manufacturer、volume、priceです。
「insert into meigara(name, nameKana, dosu, koji, sweetPotatoName, manufacturer, volume, price) values('がんこ焼酎屋', 'がんこしょうちゅうや', 25, '白', 'ジョイホワイト', '大石酒造', 1.8 , 2630);」のSQL文を使用してimoshochuCatalogItemのコンストラクタで追加した銘柄の数だけ作成します。変えるところは、values以降の()の部分です。meigaraテーブルをつくるのが面倒な方のために、サンプルコードにimoshop.sqlがあります。MySQL Workbenchなどを使用してテーブルを作成してください。
ImoshochuCatalogDAOImplクラスを修正
図18がJDBCのAPIを使ってデータベースにアクセスし、その戻り値をArrayListとして返すgetImoshochuCatalogListメソッドを持つクラスです。このクラスを作成するには12行目のcom.mysql.jdbc.Driverクラスを含むjarファイルをライブラリに追加する必要があります。[プロジェクト]-[ImoshochuWeb01]-[ライブラリ]と操作し、右クリックし[ライブラリを追加]を選択すると「ライブラリを追加」画面が開きます。[大域ライブラリ]を開き[MySQL JDBC ライブラリ]を選択します。[ライブラリを追加]ボタンをクリックすると、ライブラリにmysql-connector-java-5.1.6-bin.jarが追加されます。これでcom.mysql.jdbc.DriverクラスをClassのforNameメソッドでロードすることが可能になります。
001:public class ImoshochuCatalogDAOImpl implements ImoshochuCatalogDAO {
002:
003: private final static String url =
"jdbc:mysql://localhost:3306/imoshop";
004: private final static String sql = "select * from meigara";
005:
006: public ArrayList getImoshochuCatalogList() {
007: Connection conn = null;
008: Statement statement = null;
009: ResultSet rs = null;
010: ArrayList imoCatalog = new ArrayList();
011: try {
012: Class.forName("com.mysql.jdbc.Driver");
013: conn = DriverManager.getConnection(url,
"root", "●●●●");
014: statement = conn.createStatement();
015: rs = statement.executeQuery(sql);
016: ImoshochuCatalogItem imoItem = null;
017: while(rs.next()) {
018: imoItem = new ImoshochuCatalogItem();
019: imoItem.setName(rs.getString("name"));
020: imoItem.setNameKana(rs.getString("nameKana"));
021: imoItem.setDosu(rs.getInt("dosu"));
022: imoItem.setKoji(rs.getString("koji"));
023: imoItem.setSweetPotatoName(rs.getString("sweetPotatoName"));
024: imoItem.setManufacturer(rs.getString("manufacturer"));
025: imoItem.setVolume(rs.getFloat("volume"));
026: imoItem.setPrice(rs.getInt("price"));
027: imoCatalog.add(imoItem);
028: }
029: } catch(SQLException se) {
030: se.printStackTrace();
031: } catch(Exception e) {
032: e.printStackTrace();
033: } finally {
034: try {
035: if (statement != null) {
036: statement.close();
037: }
038: } catch(SQLException se) {
039: se.printStackTrace();
040: }
041: try {
042: if (rs != null) {
043: rs.close();
044: }
045: } catch(SQLException se) {
046: se.printStackTrace();
047: }
048: try {
049: if (conn != null) {
050: conn.close();
051: }
052: } catch(SQLException se) {
053: se.printStackTrace();
054: }
055: }
056: return imoCatalog;
057: }
058:}
データベースへは、ドライバクラスをロードし(12行目)、DriverManagerのgetConnectionメソッドを使い(13行目)接続します。getConnectionメソッドの第1引数はimoshopデータベースのURL、第2引数と第3引数は、データベースへ接続するのに認証が必要な場合設定する必要があります。第2引数はユーザ名、第3引数がパスワードです。これらは図16で設定したものです。
データベースへ接続後、SQL文を実行するには、Statementクラスを使います。4行目がSQL文ですが、プレースフォルダを持たないSQL文の場合、Statementクラスを使用します。プレースフォルダを使用する場合、PreparedStatementクラスを使います。PreparedStatementクラスやプレースフォルダは次回以降に説明します。13行目でConnectionオブジェクトを取得し、14行目でそのオブジェクトからStatementオブジェクトを取得します。15行目でStatementオブジェクトのexecuteQueryメソッドの引数にSQL文を設定し呼び出すと、データベースへ検索を行い結果をResultSetオブジェクトで返します。ResultSetからデータを取り出す処理が19行目から27行目です。取りだす値の型によりメソッドも異なります。String型、Int型、Float型ではそれぞれgetString、getInt、getFloatメソッドを使用します。引数はmeigaraテーブルで定義したカラム名です。17行目から29行目がImoshochuCatalogItemを作りArrayListに追加する処理です。
注意しなければならないのは、Statement、Connection、ResultSetオブジェクトはリソースを消費するため、使い終わったらcloseメソッドでリソースの解放を行わなければなりません。したがって、これらのリソースを解放する処理を33行目以下のfinally節で行っています。try節の中でclose処理を行えばいいように思えますが、Statement、Connection、ResultSetの順でclose処理を行うとした場合、Statementのクローズ処理に失敗すると、ConnectionやResultSetのクロース処理が行われないため、Exceptionの発生に関係なく実行されるfinally節の中でcloseするのが好ましいと筆者は考えています。ただし、finally節においても例外が発生する場合は図18の39、46、53行目のようにprintStackTraceでログに出力するか、Exceptionクラスをthrowするかは例外処理の設計次第となります。主にソフトウェアアーキテクトが行う仕事です。ここで大切なのはリソースの解放です。Javaはガベージコレクションがあるからメモリ管理は不要だと入門者の方は勘違いしやすいですが、ガベージコレクションの対象となるのは、オブジェクトがnullか、上記オブジェクトのように明示的にclose処理を行ったものが対象となります。一番メモリリークが発生しやすいところなので注意が必要です。
最後にreturn文によりImoshochuCatalogItemのArrayListであるimoCatalogを呼び出し元に返しています。これ以降の処理の流れは全く同じであるため、省略します。


