オープンソースで作る Java+DB

特集 オープンソースで作るJava+DB
第2回 コードから学ぶJSPのデータベースアクセスの基礎 (7/8)

データベースから読み込む

 次に、投稿した掲示板のレコードを読み込み、そしてユーザーが確認可能な形式に表示するよう処理をまとめていこう。

 この個所のプログラムは、リスト4のようになる。リスト4は、投稿内容すべてを新しいもの順に表形式で表示するものであり、実行結果は、Fig.4に示す通りだ。

リスト4 keijiread.jspファイル

1: <%@ page contentType="text/html; charset=EUC-JP" %>
2: <%@ page import="java.sql.*" %>
3: <%@ include file="code.jsp" %> <!-- 「JSPプログラミング入門」で作成したコード -->
4:
5: <HTML>
6: <BODY>
7: <DIV align="CENTER">
8: <H1>投稿一覧</H1>
9: <%
10: // データベースから読み取る処理
11:
12: // PostgreSQLのドライバを読み込む
13: Class.forName("org.postgresql.Driver");
14:
15: Connection conn = null;
16: Statement stmt = null;
17: ResultSet rs = null;
18:
19: try
20: {
21: // データベースに接続する
22: conn = DriverManager.getConnection(
  "jdbc:postgresql:sampledb",
  "dbuser", // ユーザー名
  "mypassword"); // パスワード
23:
24: // クエリーを実行する
25: stmt = conn.createStatement();
26:
27: // 実行して結果セットを取得する
28: rs = stmt.executeQuery(
  "SELECT * FROM Keiji ORDER BY writedate DESC");
29:
30: // 結果セットの分だけループして表示する
31: while (rs.next())
32: {
33: String username = rs.getString("name");
34: String email = rs.getString("email");
35: if (rs.wasNull())
36: {
37: email = "メールなし";
38: }
39: Timestamp writedate = rs.getTimestamp("writedate");
40: String host = rs.getString("host");
41: if (rs.wasNull())
42: {
43: host = "ホスト不明";
44: }
45: String title = rs.getString("title");
46: String msg = rs.getString("body");
47: %>
48: <TABLE border="1" width="80%">
49: <TR>
50: <TH>投稿者</TH><TD><%= htmlencode(username) %></TD>
51: </TR>
52: <TR>
53: <TH>メールアドレス</TH><TD><%= htmlencode(email) %></TD>
54: </TR>
55: <TR>
56: <TH>投稿日</TH><TD><%= htmlencode(writedate.toString()) %></TD>
57: </TR>
58: <TR>
59: <TH>投稿元アドレス</TH><TD><%= htmlencode(host) %></TD>
60: </TR>
61: <TR>
62: <TH>タイトル</TH><TD><%= htmlencode(title) %></TD>
63: </TR>
64: <TR>
65: <TH>本文</TH><TD><%= htmlencode(msg) %></TD>
66: </TR>
67: </TABLE>
68: <BR>
69: <%
70: }
71: }
72: catch (SQLException e)
73: {
74: out.println(e.getStackTrace().toString());
75: }
76: finally
77: {
78: // 接続を閉じる
79: if (rs != null)
80: {
81: rs.close();
82: }
83: if (stmt != null)
84: {
85: stmt.close();
86: }
87: if (conn != null)
88: {
89: conn.close();
90: }
91: }
92: %>
93: </DIV>
94: </BODY>
95: </HTML>

Fig.4 リスト4の実行結果

fig04.gif

データベースからのレコードの取り出し

 データベースからレコードを読み取る場合も、データベースに接続して、クエリーを送信し、データベースから切断する、という基本的な流れは変わらない。変わる部分は、クエリーとしてSELECT文を送信し、その結果をどのようにして受け取るのかという点だ。

 リスト4の28行目にあるように、SELECT文など、レコードを返すクエリーを送信するときには、StatementオブジェクトのexecuteQueryメソッドを用いればよい。

27: // 実行して結果セットを取得する
28: rs = stmt.executeQuery(
   "SELECT * FROM Keiji ORDER BY writedate DESC");

 executeQueryメソッドを呼び出すと、戻り値として、結果レコードにアクセスするためのResultSetオブジェクトが得られる。

One Point!

リスト4では、パラメータクエリーではないクエリーを用いているが、SELECT文の実行にパラメータクエリーを使うこともできる。SELECT文は、WHERE句で条件の絞り込みができるから、たとえば、データベースを検索してその結果を返すWebアプリケーションを構築したい場合には、PreparedStatementオブジェクトを使ってパラメータクエリーとして構成し、ユーザーが入力フォームに入力した条件の値をWHERE句のパラメータとして埋め込んで実行するという処理をすればよい。

 ResultSetオブジェクトは、結果レコードを1レコード分だけ保持する。そして、nextメソッドを呼び出すたびに次のレコードを取得するという仕組みを持つ。nextメソッドを呼び出した際、それ以上にレコードが存在しない場合には、戻り値として「false」が得られる。

 StatementオブジェクトのexecuteQueryメソッドを呼び出した際には、ResultSetオブジェクトは、Fig.5に示すように、結果として得られた先頭レコードよりもひとつ手前を指している。

Fig.5 ResultSetオブジェクトが指す内容

fig05.gif

 これにより、全レコードを取得したい場合には次のようなループ処理を行えばよい。

31: while (rs.next())
32: {
33〜69: …1レコード分読み取る処理…
70: }

 1レコード分の列の値を取得するには、ResultSetオブジェクトの「get型名」のメソッドを用いる(表3)。

表3 ResultSetオブジェクトにおいて、列の値を取得するための主なメソッド(一部のみ抜粋)

メソッド名
setBoolean boolean
setByte byte
setDate Date
setDouble double
setFloat float
setInt int
setLong long
setShort short
setString String
setTime Time
setTimestamp Timestamp

 たとえば、リスト4の33行目では、次のようにしてname列の値を取得していることが分かる。

33: String username = rs.getString("name");

One Point!

リスト4では、「get型名」のメソッドの引数に列名を渡すことで、該当列の値を取得している。しかし「get型名」のメソッドは引数に列の番号(先頭列を1とした序数)を渡すこともでき、この場合には列名で指定するよりも、列番号を渡したほうが処理が多少高速となる。

 該当列が「Null」値であるかどうかを調べるには、wasNullメソッドを用いる。wasNullメソッドは、直前の“get型名”のメソッドで読み取った値がNull値である場合にtrue、そうでなければfalseを返す。たとえば、34〜38行目では、次のようにして、email列がNull値であるかどうかを調べている。

37: String email = rs.getString("email");
38: if (rs.wasNull())
   // 直前がgetString("email")なのでemail列がNullかどうかを調べるという意味になる
39: {
40: email = "メールなし";
41: }

One Point!

列の値がNull値である場合、「get型名」の結果は、型ごとに違う、Null値に似た値となる。たとえば、getIntやgetShort、getLong、getFloat、getDoubleのように数値を返すメソッドの場合には、0、getStringのように文字列を返すメソッドの場合には、(Javaの)null、getBooleanのようにboolean型を返すメソッドの場合にはfalseとなる。

 列の値を読み取ったならば、JSPの“<%= 値 %>”の書式を使って、クライアントにその値を出力すればよい。たとえば、投稿者を表示する部分は次のようになっている。

50: <TH>投稿者</TH><TD><%= htmlencode(username) %></TD>

 ここで呼び出しているhtmlencodeメソッドは、連載「JSPプログラミング入門 第3回」の記事内で解説したHTMLエンコードを行うためのものだ。

One Point!

JSPプログラミング入門で作成したhtmlencodeメソッドでは、改行コードを「<BR>」に置換するという処理を実装していないので、ユーザーがFig.2にて改行を含んだ本文を入力したとき、それが正しく反映されない。正しく反映させるには、htmlencodeメソッド内に、次のように改行(“\n”)を「<BR>」に置換する処理を加えておけばよい。

public String htmlencode(String original)
{

…略…

switch (c)
{
…前略…
case '\n':
retVal.append("<BR>");
…後略…
}
…略…
}

前のページへ | 1 2 3 4 5 6 7 8 | 次のページへ

[大澤文孝,ITmedia]