Swing JDBC アプレット

Revised: 9th/Sep./2002

テーブルの作成

以下で利用するためのテーブルを作成しましょう。

C:\mysql\bin>mysql test
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4 to server version: 3.23.49-nt

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> create table addr
    -> (name char(20),
    -> access char(30));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into addr values ('菅井', 'sugai@fides.dti.ne.jp');
Query OK, 1 row affected (0.04 sec)

mysql> select * from addr;
+------+-----------------------+
| name | access                |
+------+-----------------------+
| 菅井 | sugai@fides.dti.ne.jp |
+------+-----------------------+
1 row in set (0.00 sec)

mysql> \q
Bye

C:\mysql\bin>

testデータベースにaddrテーブルが作成されました。

Swing の MVC モデル

出力結果をGUIのテーブルに表示させて見ましょう。

ResultSetのデータはテーブル形式なので、SwingではJTableを使って表示することになります。JTableではjavax.swing.table.TableModelインタフェース型オブジェクトとしてデータを取得します。実際には、TableModelインタフェースのデフォルトの実装がjavax.swing.table.AbstractTableModelで提供されているので、これを継承したサブクラスを作ることになります。この抽象クラスから具象TableModelオブジェクトを作成するには、次の三つのメソッドを実装する必要があります。

public int getRowCount();                         // モデルの列数を返します。
public int getColumnCount();                      // モデルの行数を返します。
public Object getValueAt(int row, int column);    // row と column にあるセルの値を返します。

例えば、10行5列のJTableを作るには、次のコードが必要になります。

// TableModel オブジェクトの作成
TableModel dataModel = new AbstractTableModel() {
	public int getRowCount() {
		return 10;	// 行数
	}
	public int getColumnCount() {
		return 5;	// 列数
	}
	public Object getValueAt(int row, int col) {
		return 指定されたセルの戻り値;
	}
};

// JTable のデータをモデルから取得
JTable table = new JTable(dataModel);

// Jtable を JScrollPane を通して見る
JScrollPane scrollpane = new JScrollPane(table);

ResultSetからJTaleを作る場合もTableModelを利用します。次の断片は、ResultSetオブジェクトから列数や型などのメタデータを取得し、AbstractTableModelを実装するものです。java.util.Vectorオブジェクトを用いていることにも注目してください。Vectorオブジェクトは、配列と似ていますが、要素をjava.lang.Objectオブジェクトとして扱い、各行の要素数の追加が可能です。

resultSet = statement.executeQuery(query);
metaData = resultSet.getMetaData();	// ResultSetのメタデータの取得

int numberOfColumns =  metaData.getColumnCount();	// 列数を取得
columnNames = new String[numberOfColumns];	// 列名を保持する配列の作成

for(int column = 0; column < numberOfColumns; column++) {
	columnNames[column] = metaData.getColumnLabel(column + 1);	// 列名を取得
}

rows = new Vector();	// ResultSet全体のデータを保持するベクトル
while (resultSet.next()) {
	Vector newRow = new Vector();	// ResultSetの一行分のデータを保持するベクトル
	for (int i = 1; i <= getColumnCount(); i++) {
		newRow.addElement(resultSet.getObject(i));	// 各データを取得し追加
	}
rows.addElement(newRow);	// 各行を追加
}

上記の断片で型宣言されていない変数は、このクラスのメンバー変数として宣言しておきます。ResultSetのテーブルはVectorオブジェクトのrowに保持されました。テーブルの各行はVectorオブジェクトのnewRowに保持され、各列名がString型配列columnNamesに保持されています。以上三つのオブジェクトを使って、AbstractTableModelの実装メソッドは次のように書けます。

public int getColumnCount() {
	return columnNames.length;
}
public int getRowCount() {
	return rows.size();
}
public Object getValueAt(int aRow, int aColumn) {
	Vector row = (Vector)rows.elementAt(aRow);
	return row.elementAt(aColumn);
}

このように作ったTableModelをmodelオブジェクトとしてインスタンス化すると、JTableは次のように書けます。

JTable table = new JTable(model);
JScrollPane scrollpane = new JScrollPane(table);

ソースコード

以上を踏まえて、Swingアプレットは次のように書けます。ここでは、AbstractTableModelのサブクラスをDataModel、DBMS接続/SQL文発行オブジェクトをPersistentManager、アプレットをDBCSwingAppletとします。

JDBCSwingApplet.java:

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.sql.*;
import java.util.*;

public class JDBCSwingApplet extends JApplet {
	TableModel model;

	public void init() {
		// DBMS への接続
		PersistenceManager persistMgr = new PersistenceManager();
		// SQL 文の発行とモデルの取得
		try {
			ResultSet rs = persistMgr.executeSQL("SELECT * FROM addr;");
			model = new DataModel(rs);
		} catch (SQLException e) {
			e.printStackTrace();
			return;
		}

		// JTable の作成
		JTable table = new JTable(model);
		JScrollPane scrollpane = new JScrollPane(table);

		// コンテント・ペインの取得
		Container cont = getContentPane();
		cont.add(scrollpane);
	}
}

class PersistenceManager {
	Statement stmt;

	// DBMS への接続
	PersistenceManager() {
		try {
			// JDBC Driver の登録
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			// データベースへの接続
			Connection con = DriverManager.getConnection(
			    "jdbc:mysql://localhost/test", "root", "passwd");
			// SQL ステートメント・オブジェクトの作成
			stmt = con.createStatement();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// SQL 文の発行
	ResultSet executeSQL(String str) throws SQLException {
		return stmt.executeQuery(str);
	}
}

class DataModel extends AbstractTableModel {
	String[] columnNames;
	Vector rows = new Vector();

	// モデルの作成
	DataModel(ResultSet rs) throws SQLException {
		ResultSetMetaData metaData = rs.getMetaData();	// ResultSetのメタデータの取得

		int numberOfColumns =  metaData.getColumnCount();	// 列数を取得
		columnNames = new String[numberOfColumns];	// 列名を保持する配列の作成

		for(int column = 0; column < numberOfColumns; column++) {
			columnNames[column] = metaData.getColumnLabel(column + 1);	// 列名を取得
		}

		rows = new Vector();	// ResultSet全体のデータを保持するベクトル
		while (rs.next()) {
			Vector newRow = new Vector();	// ResultSetの一行分のデータを保持するベクトル
			for (int i = 1; i <= getColumnCount(); i++) {
				newRow.addElement(rs.getObject(i));	// 各データを取得し追加

			}
			rows.addElement(newRow);	// 各行を追加
		}
	}

	// 以下 AbstractTableModel の実装
	public String getColumnName(int column) {
		if (columnNames[column] != null) {
			return columnNames[column];
		} else {
			return "";
		}
	}
	public int getColumnCount() {
		return columnNames.length;
	}
	public int getRowCount() {
		return rows.size();
	}
	public Object getValueAt(int aRow, int aColumn) {
		Vector row = (Vector)rows.elementAt(aRow);
		return row.elementAt(aColumn);
	}
}

このアプレットも、実行するためにはJDBCドライバが必要ですが、アプレットは一般に自分がダウンロードされたサーバ・マシンとしか通信できず、自分をダウンロードしたクライアント・マシンのローカル・ファイルに触ることができません。従って、ローカル・マシンのCLASSPATHで切ってあるMySQL Connector/JドライバのJARファイルを使うことができません。この問題を解決するためには、JARファイルもこのアプレットと共にサーバ・マシンからダウンロードし、それを使う必要があります。そのためには、HTMLのapplet要素にarchive属性を与えてサーバ・マシン上のJARファイルを指定します。

JDBCSwingApplet.html:

<p><applet code="JDBCSwingApplet" archive="mysql-connector-java-2.0.14-bin.jar"
	width="200" height="100">
アプレットが実行できない場合の代替内容
</applet></p>

"JDBCSwingApplet.java"をjavacでコンパイルして生成した"JDBCSwingApplet.class"と、"JDBCSwingApplet.html"と、"mysql-connector-java-2.0.14-bin.jar"を同じディレクトリに置いてください。別のディレクトリに置くときは、applet要素にcodebase属性を指定します。詳細はW3CによるHTML 4.01の仕様書をご覧ください。



Copyright © 2002 SUGAI, Manabu. All Rights Reserved.
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送