JSPによるデータベース・アクセス
 JSPからデータベースにアクセスするには、他のJavaアプリケーションと同様、 JDBCを使います。 ここではまず、指定したパラメータによってデータベースに接続して、 JDBCのConnectionオブジェクトを返すところまでの処理を行うクラス 「DbcmSimpleAdaptor」を作り、 これをJSPから呼び出すことを考えます。
/**
 * DbcmSimpleAdaptor.java
 *
 * @author K.Heijima
 * @date 2001/05/25 - 2001/12/23
 */
import java.io.*;
import java.sql.*;
import java.util.Vector;
import ushi.util.*;

/**
 * 各RDBMS固有の情報に依存する部分を吸収するためのインターフェースです。
 *
 * 各RDBMS向けのJDBCドライバ経由でDbcmを使用するには、そのドライバの接続
 * URLなどを定義してDbcmSpecを実装する必要があります。
 */
interface DbcmSpec {
    public String getDriverName();
    public Connection getConnection (String hostname, int port,
 String database, String user, String password) throws SQLException;
    public Connection getConnection (String hostname,
 String database, String user, String password) throws SQLException;
}

/**
 * PostgreSQLの接続情報を実装したクラスです。
 *
 */
class DbcmPostgreSQLSpec implements DbcmSpec {
    public String getDriverName(){
	return "org.postgresql.Driver";
    }
    public Connection getConnection(String hostname, int port,
 String database, String user, String password)
    throws SQLException {
	return DriverManager.getConnection("jdbc:postgresql://" +
            hostname + ":" + Integer.toString(port) + "/" + database,
            user, password);
    }
    public Connection getConnection (String hostname,
 String database, String user, String password) throws SQLException {
	return this.getConnection(hostname, 5432, database, user, password);
    }
}

/**
 * MySQLの接続情報を実装したクラスです。
 */
class DbcmMySQLSpec implements DbcmSpec {
    public String getDriverName(){
	return "org.gjt.mm.mysql.Driver";
    }
    public Connection getConnection(String hostname, int port,
 String database, String user, String password)
    throws SQLException {
	return DriverManager.getConnection("jdbc:mysql://" +
        hostname + ":" + Integer.toString(port) + "/" + database +
        "?useUnicode=true&characterEncoding=EUC_JP",
	user, password);
    }
    public Connection getConnection (String hostname,
 String database, String user, String password) throws SQLException {
	return this.getConnection(hostname, 3306, database, user, password);
    }
}

/**
 * Cloudscapeの接続情報を実装したクラスです。
 */
class DbcmCloudscapeSpec implements DbcmSpec {
    public String getDriverName(){
	return "COM.cloudscape.core.JDBCDriver";
    }
    public Connection getConnection(String hostname, int port,
 String database, String user, String password)
    throws SQLException {
	return DriverManager.getConnection("jdbc:cloudscape:" + database +
          ";shutdown=true");
    }
    public Connection getConnection (String hostname,
 String database, String user, String password) throws SQLException {
	return this.getConnection(hostname, -1, database, user, password);
    }
}

/**
 * Oracle(Type 4 Thin Driver)の接続情報を実装したクラスです。
 */
class DbcmOracleThinSpec implements DbcmSpec {
    public String getDriverName(){
	return "oracle.jdbc.driver.OracleDriver";
    }
    public Connection getConnection(String hostname, int port,
 String database, String user, String password)
    throws SQLException {
	return DriverManager.getConnection("jdbc:oracle:thin:@" +
            hostname + ":" + Integer.toString(port) + ":" + database
            /* + "?user=" + user + ";password=" + password */ ,
            user, password);
    }
    public Connection getConnection (String hostname,
 String database, String user, String password) throws SQLException {
	return this.getConnection(hostname, 1521, database, user, password);
    }
}

/**
 * JDBCでデータベースに接続するための汎用クラスです。
 * このクラスは接続(Connection)を内部的に持っていない点に注意が必要です。
 * 接続仕様であるDbcmSpecから,それに合うRDBMSに接続を試み、
 * Connectionオブジェクトを作成して返すことだけがこのクラスの仕事です。
 *
 * @see ushi.jdbc.DbcmAdaptor
 * @see ushi.jdbc.Dbcm
 */
public class DbcmSimpleAdaptor {
    String driverSpec = null;
    String hostName = "localhost";
    int port = -1;
    String database = "";
    String userName = "";
    String password = "";
    DbcmSpec ds;

    /**
     * コンストラクタです。この引数のないコンストラクタはJavaBeans
     * として生成するときに使うもので、後で後続のメソッドを使って
     * 各プロパティをセットする必要があります。
     */
    public DbcmSimpleAdaptor(){

    }

    /**
     * コンストラクタです。こちらは接続(connect)までに最低限設定が
     * 必要なパラメータを全て指定します。
     * 実際の接続はconnectメソッドで行います。接続の成否はそのときに
     * わかります。
     * @param driverSpec JDBCドライバの種類(oracle-thin, postgresqlなど)
     * @param hostName RDBMSサーバのホスト名
     * @param port RDBMSサーバのリスナーのポート番号
     * @param database データベース識別子
     * @param userName 接続ユーザ名
     * @param password パスワード
     */
    public DbcmSimpleAdaptor(String driverSpec, String hostName, int port,
		       String database, String userName, String password)
    throws ClassNotFoundException {
	setDriverSpec(driverSpec);
	setHostName(hostName);
	setPort(port);
	setDatabase(database);
	setUserName(userName);
	setPassword(password);
    }

    /**
     * JDBCドライバの種類を設定し,JDBCドライバをロードします。
     * @param did JDBCドライバ識別文字列。「postgresql」「cloudscape」など。
     */
    public final void setDriverSpec(String driverSpec)
	throws ClassNotFoundException {
	this.driverSpec = driverSpec;

	// JDBCドライバをロードします。
	if(driverSpec.equals("postgresql")){
	    this.ds = new DbcmPostgreSQLSpec();
	}
	else if(driverSpec.equals("cloudscape")){
	    this.ds = new DbcmCloudscapeSpec();
	}
	else if(driverSpec.equals("oracle-thin")){
	    this.ds = new DbcmOracleThinSpec();
	}
	else if(driverSpec.equals("mysql")){
	    this.ds = new DbcmMySQLSpec();
	}
	else{
	    // 想定外(下の例外が飛びます)
	    this.ds = null;
	}
	// JDBCドライバのクラスを探して来ます。見つからなければ、
	// ClassNotFoundExceptionが飛びます。
	Class.forName(this.ds.getDriverName());
    }

    /**
     * JDBCドライバの種類を返します。
     */
    public final String getDriverSpec(){ return driverSpec; }

    /**
     * RDBMSサーバのホスト名を設定します。
     * @param hostname RDBMSのサーバープロセスが動いているホスト名
     */
    public final void setHostName(String hostName){
	this.hostName = hostName;
    }

    /**
     * RDBMSサーバのホスト名を返します。
     */
    public final String getHostName(){
	return hostName;
    }

    /**
     * RDBMSサーバのリスナーのポート番号を設定します。
     * @param port RDBMSのリスナーが待機しているポート番号
     */
    public final void setPort(int port){
	this.port = port;
    }

    /**
     * リスナーのポート番号を返します。
     */
    public final int getPort(){
	return port;
    }


    /**
     * 接続するデータベース名を設定します。
     * @param database RDBMSが各々定義しているデータベース名
     */
    public final void setDatabase(String database){
	this.database = database;
    }

    /**
     * 接続するデータベース名を返します。
     */
    public final String getDatabase(){
	return database;
    }

    /**
     * 接続ユーザ名を設定します。
     * @param user RDBMSへ接続(ログイン)するときのユーザ名
     */
    public final void setUserName(String userName){
	this.userName = userName;
    }

    /**
     * 接続ユーザ名を返します。
     */
    public final String getUserName(){
	return userName;
    }

    /**
     * 接続パスワードを設定します。
     * @param password RDBMSへ接続(ログイン)するときのパスワード
     */
    public final void setPassword(String password){
	this.password = password;
    }

    /**
     * 接続パスワードを返します。
     */
    public final String getPassword(){
	return password;
    }

    /**
     * データベースに接続します。
     * このメソッドを実行するまでに、JDBCドライバの種類、ホスト名、
     * ポート番号(省略可)、データベース名、接続ユーザ名、パスワードを
     * アクセサメソッドによってセットしておく必要があります。
     */
    public Connection connect()	throws SQLException {
	Connection conn;
	// ポート番号は省略されたら、各RDBMSデフォルトの値を使います。
	if(this.port > 0){
	    conn = this.ds.getConnection(hostName, port, database, userName, password);
	}
	else{
	    conn = this.ds.getConnection(hostName, database, userName, password);
	}
	return conn;
    }
}
/* end. */

これをコンパイルして、できた .class ファイルを $TOMCAT_HOME/webapps/{appname}/WEB-INF/classes にコピーします。


<%@ page language="java" contentType="text/html;charset=EUC_JP" %>
<%@ page import="java.sql.*, DbcmSimpleAdaptor" %>
<html>
<head><title>ログイン</title></head>
<body bgcolor="white">

<%!
/**
 * データベースに接続して、パスワード認証を行います。
 * ログインOKなら真、NGなら偽を返します。
 */
private boolean checkLogin(String userID, String password)
throws SQLException, ClassNotFoundException {
    boolean result;
    DbcmSimpleAdaptor adaptor = new DbcmSimpleAdaptor();
    adaptor.setDriverSpec("postgresql");
    adaptor.setHostName("localhost");
    adaptor.setPort(5432);
    adaptor.setDatabase("udb");
    adaptor.setUserName("urano");
    adaptor.setPassword("");

    Connection con = adaptor.connect();
    String sql = "SELECT PASSWORD FROM USERS WHERE USER_ID = ?";
    PreparedStatement ps = con.prepareStatement(sql);
    ps.setString(1, userID);

    ResultSet rset = ps.executeQuery();
    if(! rset.next()){
        result = false;
    }
    else{
        String dbpass = rset.getString(1).toLowerCase();
        result = password.toLowerCase().equals(dbpass);
    }
    rset.close();
    con.close();
    return result;
}
%>

<%
String userID = request.getParameter("user_id");
String password = request.getParameter("password");
if(userID == null){
%>
    <form action="dbsimple.jsp" method="post">
    ユーザID:<input type="text" name="user_id"><br>
    パスワード:<input type="password" name="password"><br>
    <br>
    <input type="submit" value="ログイン">
    </form>
<%
}
else{
    boolean result;
    try {
        if(checkLogin(userID, password)){
%>
            <h1>ログインしました。</h1>
            ようこそ、<%= userID %>さん。
<%
        }
        else{
%>
            <h1>おおっと</h1>
            ログインできません。
            <a href="<%= response.encodeURL("dbsimple.jsp") %>">こちら</a>
            に戻って再度入力を試して下さい。
<%
        }
    } catch(SQLException ex){
%>
        <h1>おおっと</h1>
        データベース接続エラーが発生しました。<br>
        <%= ex.toString() %>
<%
    }
}
%>
</body>
</html>

 自前のクラスを使うことにより、データベースへの接続は、

    DbcmSimpleAdaptor adaptor = new DbcmSimpleAdaptor();
    adaptor.setDriverSpec("postgresql");
    adaptor.setHostName("localhost");
    adaptor.setPort(5432);
    adaptor.setDatabase("udb");
    adaptor.setUserName("urano");
    adaptor.setPassword("");
    Connection con = adaptor.connect();
と簡単に行うことができるようになりました。 接続までをJavaクラス化して、接続以後(問合せを実行する処理) はJSPで書くなんて、ほんとは少しおかしいのですが、 ここではサンプルということで… データベースアクセスの用途が明確に決まれば、それに特化した Javaクラスを定義して、JSPへのJava記述は最小限になるようにすべきです。 例えばこの例では、データベースの「USERS」という表を検索して、 その列USER_IDがユーザ名、PASSWORDがパスワードを表すとはっきり分かっているならば、 ユーザ名とパスワードを渡すとログインOKかNGのどちらかが返る、 というはっきり目的(パスワード認証)に特化したメソッドを実装したクラスを Javaで書いてパックしてしまったほうが後々すっきりするでしょう。

Java Top
(first uploaded 2001/12/24, KQ Taura)

G|Cg|C@Amazon Yahoo yV

z[y[W yVoC[UNLIMIT1~] COiq COsI