Servlet/JSP/JavaBeans (J2EE Application) を組み合わせたデータベースアクセス

データベースをアクセスして結果をテーブルで表示するアプリケーションを Servlet/JavaBeans/JSP の組み合わせで作ってみました。

各オブジェクトの構成は以下のようになっています。

Customer

データを一行ずつ格納するオブジェクト
内部フィールドとして custno、custname、addr を持ち、その値をセットまたは取り出すための setter/getter メソッドを持っています。

CustomerData

connection オブジェクトを引数にとって、データベースの検索を行う SQL文を実行し、その検索結果を Customer オブジェクトに格納するクラス
UDB for iSeries 上のテーブルとそのカラムと Customer オブジェクトとその内部フィールドとのマッピングを行います。
検索結果(Customerオブジェクトの集合である Vector オブジェクト)の行を次に移動するための next メソッドを持ち、その時にポイントされている Customerオブジェクトから custno、custname、addr を取り出すための getter メソッドを持っています。

CustomerServlet

全体のコントローラとして機能するサーブレット
データソースをルックアップしてデータベースへの接続オブジェクトの作成を行い、それを CustomerData に渡してデータベースの検索を行って結果を格納してもらいます。
その CustomerData オブジェクトを、今度は CustomerList.jsp に渡して表示を行ってもらいます。

CustomerList.jsp

コントローラである CustomerServlet で、取得された結果と共にフォワードされ表示を受け持つ JSP ファイル
CutomerServlet で Request オブジェクトに 実体化された CustomerData (つまり検索結果の入ったオブジェクト)をセットされ、JSPファイルから参照します。
CustomerData オブジェクトの next メソッドを使って行を移動しながら、CustomerData オブジェクトの getter メソッドを使用して HTML の表に各カラムをセットします。

このうち CustomerList.jsp を /QIBM/UserData/WebASAdv/default/hosts/default_host/default_app/web の中に置き、Customer.class、CustomerData.class、CustomerServlet.class を /QIBM/UserData/WebASAdv/default/hosts/default_host/default_app/servlets に置きました。(デフォルトサーバーを使用している場合)

また、コンパイルには /QIBM/ProdData/java400/ext にある db2_classes.jar と jdbc2_0-stdext.jar がクラスパスに含まれている必要があります。(あと、servlet.jar も)

結果はこんなかんじになります。


それぞれのソースを見ていきましょう。

Customer.java

import java.io.Serializable;

public class Customer implements Serializable {

String custno = "";
String custname = "";
String addr = "";

public Customer () {
}

public String getCustno () {
return custno;
}

public void setCustno (String newCustno) {
custno = newCustno;
}

public String getCustname () {
return custname;
}

public void setCustname (String newCustname) {
custname = newCustname;
}

public String getAddr () {
return addr;
}

public void setAddr (String newAddr) {
addr = newAddr;
}

}

3つの内部フィールドの定義と、そのための setter/getter メソッドの定義を行っています。

CustomerData.java

import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
import java.util.Vector;
import Customer;

public class CustomerData implements Serializable {
Vector custs = new Vector();
Customer current = null;
int index = 0;

public CustomerData () {
}

public void executeQuery(Connection conn) throws SQLException {
Statement stmt = conn.createStatement();
System.out.println("Connection within bean OK");
ResultSet rs = stmt.executeQuery(
"SELECT TKBANG, TKNAKJ, TKADR1 FROM QEOL.TOKMSP"
);
System.out.println("ExecQuery within bean OK");
while (rs.next()) {
Customer cust = new Customer();
cust.setCustno(rs.getString("TKBANG"));
System.out.println("setBean within bean OK");
cust.setCustname(rs.getString("TKNAKJ"));
// System.out.println(rs.getString("TKNAKJ"));
cust.setAddr(rs.getString("TKADR1"));
custs.addElement(cust);
System.out.println("addElement within bean OK");
}
rs.close();
stmt.close();
}

public boolean next() {
if (index < custs.size()) {
current = (Customer) custs.elementAt(index);
index ++;
return true;
}
else {
return false;
}
}

public String getCustno () {
return current.getCustno ();
}

public String getCustname () {
return current.getCustname ();
}

public String getAddr () {
return current.getAddr ();
}

}

インスタンス化されただけでは特に何も起こりません。

ExecuteQueryメソッドは接続オブジェクトを引数にとり、検索を行います。

引数に受け取った接続オブジェクトをもとに SQLステートメントを作成/実行し、必要なカラムのみを取り出して、新たに生成されたCustomer オブジェクトに格納します。
そしてそれをさらに Vector オブジェクトに格納していきます。

JSPからは next メソッドを使用してそのVector オブジェクトの各行にアクセスし、getXXX(XXXはフィールド名)でフィールドを取得します。

CustomerServlet.java

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import CustomerData;

public class CustomerServlet extends HttpServlet {

public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {

try {
InitialContext ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup("jdbc/sample");
System.out.println("DataSource OK");
Connection con = ds.getConnection();
System.out.println("Connection OK");

CustomerData custsData = new CustomerData();
custsData.executeQuery(con);
System.out.println("ExecuteQuery OK");
req.setAttribute("custData", custsData);
System.out.println("setAttribute OK");

getServletContext().getRequestDispatcher("CustomerList.jsp").forward(req, res);
System.out.println("forwarding JSP OK");
con.close();
}

catch (NamingException ne) {
throw new ServletException ("Couldn't get DataSource", ne);
}


catch (SQLException se) {
throw new ServletException ("Exception during a DB access", se);
}
}
}

この中でまず最初に行われているのがデータソースオブジェクトのルックアップです。

jdbc/sample という名前でルックアップを行っていますが、これは管理コンソールから以下のようにして見ることのできる「データソース」オブジェクトを参照します。

以下のように「タスク」-「データソースの作成」で定義します。

その後は CustomerData オブジェクトを作成し、先のデータソースを使用して作成した接続オブジェクトを渡して、CustomerData オブジェクトのExecuteQueryメソッドを使用して検索結果を取得します。

その結果はそのまま CustomerData オブジェクトの中に格納されているので、これを jsp に渡される Reqest オブジェクトの中に jsp で使用される"custData"属性としてセットし、CustomerList.jsp に結果を表示させるためにフォワードします。

CustomerList.jsp

<HTML>
<HEAD>
<TITLE>得意先マスター</TITLE>
</HEAD>

<%@ page contentType="text/html;charset=Shift_JIS" %>
<%@ page language="java" import="CustomerData" %>
<jsp:useBean id="custData" scope="request" class="CustomerData" />

<BODY>
<H1>得意先マスター内容</H1>
<TABLE border="1" cellspacing="0">
<TR>
<TH>得意先番号</TH>
<TH>得意先名</TH>
<TH>住所</TH>
</TR>

<% while (custData.next()) { %>
<TR>
<TD><jsp:getProperty name="custData" property="custno" /></TD>
<TD><jsp:getProperty name="custData" property="custname" /></TD>
<TD><jsp:getProperty name="custData" property="addr" /></TD>
</TR>
<% } %>
</TABLE>

</BODY>
</HTML>

<jsp:useBean id="custData" ...> の "custData" は先のコントローラサーブレットで Request オブジェクトにセットされる属性の名前と同じです。

そしてこの名前をもとに <% while (custData.next()) ...> や <jsp:getProperty name="custData" ...> など渡されたオブジェクトへのアクセスを行います。

<jsp:getProperty name="custData" property="custno" /> と書くと、自動的に CustomerData の中の getCustno メソッドの実行が行われます。
逆に言えば、このフィールド名の最初を大文字にして get をつけたメソッドが実装されている必要があるわけです。

[Top Pageに戻る]

Ads by TOK2