SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

WTPではじめるサーバサイドJava入門

サーバサイドJava入門 Java DBによるデータベースアクセス

第8回 JSP/サーブレットからのデータベースアクセスの基本

データベースアクセスBeanの作成

 では、作成したmydatabaseデータベースのuserdataテーブルを利用するプログラムを作成してみましょう。ここでは、次のような形でWebアプリケーションを構成していくことにします。

  • データベースアクセスBeanクラス
  • データベースにアクセスするための専用クラス。一覧リストをHTMLとして生成したり、新規レコードを追加したりといったデータベース利用の機能をまとめておきます。
  • 表示用JSP
  • データベースから必要なレコードを表示するための情報を受け取って表示をしたり、新規レコードを送信するためのフォームを用意します。基本的に表示関係の機能はこのJSP自身にもたせることにします。
  • データベース操作用サーブレット
  • 新規作成のフォームが送信されたらBeanクラスを利用してレコード登録を行ったり、データの削除を行うためのサーブレットを用意します。

 表示関係は、「index.jsp」からBeanクラスを利用して表示をさせることにします。レコードの新規登録や削除といった操作は、サーブレットに送信をし、そこからBeanを利用してデータベースの操作を行った後、「index.jsp」にリダイレクトする、といった形で動くようにしましょう。

Beanクラスの定義

 では、データベース利用のためのプログラムを作成していきましょう。データベースへのアクセスを行うのは、DBAccessというクラスです。ここにデータベースを利用するために必要な機能をすべて用意しておくことにします。

package jp.codezine;

import java.sql.*;
import java.util.Properties;

public class DBAccess {

    public Connection createConnection() throws ClassNotFoundException,
            SQLException {
        Connection conn = null;
        Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
        Properties prop = new Properties();
        prop.put("user", "user");
        prop.put("password", "test");
        conn = DriverManager.getConnection(
            "jdbc:derby:C:\\DerbyDatabases\\mydatabase", prop);
        conn.setAutoCommit(true);
        return conn;
    }

    public void addRecord(int n, String nm) {
        Connection conn = null;
        Statement state = null;
        try {
            conn = createConnection();
            state = conn.createStatement();
            String query = "insert into userdata values("
                + n + ",'" + getSanitizedString(nm) + "')";
            state.execute(query);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                state.close();
                conn.close();
            } catch (Exception ex) {
            }
        }
    }

    public void removeRecord(int n) {
        Connection conn = null;
        Statement state = null;
        try {
            conn = createConnection();
            state = conn.createStatement();
            String query = "delete from userdata where number=" + n;
            state.execute(query);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                state.close();
                conn.close();
            } catch (Exception ex) {
            }
        }
    }

    public String getAllRecord() {
        return getRecord("select * from userdata");
    }
    
    public String getFindRecord(String s) {
        int n = 0;
        try {
            n = Integer.parseInt(s);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        String q = "select * from userdata where number=" + n;
        System.out.println(q);
        return getRecord(q);
    }
    
    public String getRecord(String query){
        String result = "<table border=\"1\">\n";
        Connection conn = null;
        Statement state = null;
        ResultSet rs = null;
        try {
            conn = createConnection();
            state = conn.createStatement();
            rs = state.executeQuery(query);
            while (rs.next()) {
                int number = rs.getInt("number");
                String name = rs.getString("name");
                result += "<tr>";
                result += "<td>" + number + "</td>";
                result += "<td>" + name + "</td>";
                result += "</tr>\n";
            }
            result += "</table>\n";
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                rs.close();
                state.close();
                conn.close();
            } catch (Exception ex) {
            }
        }
        return result;
    }

    // 無効化処理
    public String getSanitizedString(String s) {
        return s.replaceAll("'", "");
    }
}

 ここでは、データベースへの接続開始のための処理をcreateConnectionというメソッドにまとめ、それを呼び出して利用する形で各種のメソッドを用意してあります。用意してあるのは次のようなものです。

メソッド一覧
メソッド名機能
addRecord引数の値をレコードとして登録する。
removeRecord引数のnumberのレコードを削除する。
getAllRecord全レコードを表示するHTMLソースを返す。
getFindRecord引数のnumberのレコードを検索し表示するHTMLソースを返す。

 これらのメソッドをJSP/サーブレットから呼び出すことでデータベースを利用できるようにするわけです。

データアクセスの流れ

 データベースアクセスの基本的な手順は、どのような操作でも大体同じです。まず「ava.sql.Connection」クラスのインスタンスを作成し、これを利用して各種の操作を行うことになります。Connectionを取得し必要な処理を行うまでの部分が、データベースアクセスで最も面倒くさい部分といってよいでしょう。

Class.forName("org.apache.derby.jdbc.EmbeddedDriver");

 まず最初に行うべきは、データベースにアクセスするためのドライバークラスのロードです。これは、Class.forNameを利用します。これで引数に指定したドライバークラスをロードすると、以後のデータベースへの接続にこのクラスを利用するようになります。

 Java DBの場合、アクセスには2種類の方法があります。直接データベースにアクセスする方法と、Java DBをサーバとして起動し、クライアントからアクセスする方法です。ここでは直接アクセスをしていますので、そのためのドライバーとしてorg.apache.derby.jdbc.EmbeddedDriverクラスをロードします(サーバにクライアントとしてアクセスする場合には、org.apache.derby.jdbc.ClientDriverクラスを使います)。

Properties prop = new Properties();
prop.put("user", "user");
prop.put("password", "test");

 続いて、データベースアクセスを行うのに必要なプロパティをPropertiesインスタンスとして用意しておきます。ここでは、アクセスに使うユーザ名とパスワードを、それぞれ"user"、"password"という名前のプロパティとしてPropertiesに追加しておきます。

conn = DriverManager.getConnection(
    "jdbc:derby:C:\\DerbyDatabases\\mydatabase", prop);

 必要なものが揃ったら、DriverManager.getConnectionを呼び出してConnectionインスタンスを作成します。このgetConnectionでは、引数にアクセスするデータベースと、その他必要な情報をまとめたPropertiesを渡しています。Java DBの場合、データベースは、「jdbc:derby:データベースの指定」という形になります(クライアントからサーバにアクセスをする場合には、「jdbc:derby://ホスト名:ポート番号/データベース指定」となります)。

conn.setAutoCommit(true);

 Connection取得後、ここではオートコミット機能をONにしています。これはクエリー(SQLのコマンド文)を送信し実行するごとにトランザクションの開始と終了を自動的に行うものです。トランザクションは、関連する処理をまとめて実行するためのもので、データベースアクセスでは一定の処理をまとめて行うようにします。このsetAutoComitは、実行すると自動的にトランザクション処理を開始・終了してくれます。

 ここまでで、Connection作成のための基本的な手続きは終わりました。続いて、実際にSQLのコマンドを送信して処理を行うことになります。このコマンドには、大きく分けて2つのものがあります。単にコマンドを実行するだけのものと、実行して結果を取得し、それを利用するものです。

 まず「コマンドを実行して終わり」というタイプのものからです。レコードを追加したり削除したりといった操作は、ただ実行するだけで、その後に何らかの結果を受け取って処理するわけではありません。こうしたタイプのものは、実行は比較的簡単です。

state = conn.createStatement();

 Connectionから「Statement」というインスタンスを作成します。このStatementを使ってSQLのコマンドを実行します。

String query = "insert into userdata values("
    + n + ",'" + getSanitizedString(nm) + "')";
state.execute(query);

 実行するSQLのコマンドをテキストとして用意し、これを引数にしてStatementexecuteを呼び出します。これでコマンドが実行されます。単純にコマンドを実行するタイプのものは、これで終わりです。

 一方、レコードを表示したり、検索結果を表示するようなコマンドは、もう少し複雑です。まずStatementを用意し、コマンドを実行するという手順は同じですが、扱いが多少異なります。

state = conn.createStatement();
rs = state.executeQuery(query);

 こちらは、executeではなく、executeQueryというメソッドを利用しています。こちらは、SQLコマンドを送信し、結果を「ResultSet」というクラスのインスタンスとして受け取ります。このResultSetはデータベースからレコード情報を受け取るのに用いられるもので、この中から順にレコードの情報を取り出していくことができます。

while (rs.next()) {
    int number = rs.getInt("number");
    String name = rs.getString("name");
    result += "<tr>";
    result += "<td>" + number + "</td>";
    result += "<td>" + name + "</td>";
    result += "</tr>\n";
}
result += "</table>\n";

 返されたResultSetから全レコードの情報を取り出しています。ResultSetは、カレントレコード(現在選択されているレコード)の概念を持っており、「getInt」「getString」といったメソッドを呼び出すことで、現在のカレントレコードの値を取り出すことができます。カレントレコードは、nextメソッドを呼び出すごとに移動していきます。一番最後のレコードまで移動し、更にnextを呼び出すとfalseが返され、whileから抜け出すことができます。

次のページ
新規・削除用サーブレットの作成

この記事は参考になりましたか?

WTPではじめるサーバサイドJava入門連載記事一覧

もっと読む

この記事の著者

掌田 津耶乃(ショウダ ツヤノ)

三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1556 2007/08/14 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー