データの検索
13.3 データの検索
本節では、JDBCを利用してWebアプリケーションからデータを検索する方法について、以下の3つのプログラムを作成しながら学習します。
・ 13.3.1 : 全てのデータを一覧で表示するプログラム
・ 13.3.2 : 絞り込み検索を行いデータを表示するプログラム
・ 13.3.3 : 1件のデータを検索し表示するプログラム
13.3.1と13.3.2で作成するプログラムでは、複数のレコードのデータをデータベースから取得し画面に表示するため、DTOクラスのオブジェクトをArrayListに格納しメソッドの戻り値などに利用しています。
一方13.3.3で作成するプログラムでは、1レコード分のデータのみを扱うため、DTOクラスのオブジェクトをそのままメソッドの戻り値などに利用します。このデータ管理の違いや取得したデータを画面に一覧として表示する処理は重要な部分なので、しっかりと理解してください。
13.3.1 全てのデータを表示する
「全てのデータの検索」は、データ検索を行うプログラムの基本となります。
まずは、全てのデータを検索するプログラムを作成して、WebアプリケーションでのJDBCの利用方法について学習しましょう。
全てのデータを一覧で表示するプログラム
Webアプリケーション上でJDBCを利用して全てのデータを検索し、Webブラウザに一覧として表示します。
このプログラムではデータベースから複数行のデータを取得するため、DTOクラスとArrayListクラスを利用してデータを保持します。
実行結果

アプリケーション構成

① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch13
③ 名前 :AccountDao1
➢ AccountDao1.java
6 | public class AccountDao1 { |
9 | private static String RDB_DRIVE = "com.mysql.jdbc.Driver"; |
10 | private static String URL = "jdbc:mysql://localhost/accountdb"; |
11 | private static String USER = "root"; |
12 | private static String PASS = "root123"; |
15 | public static Connection getConnection(){ |
17 | Class.forName(RDB_DRIVE); |
18 | Connection con = DriverManager.getConnection(URL, USER, PASS); |
21 | throw new IllegalStateException(e); |
25 | //データベースから全てのアカウント情報の検索を行うメソッド |
26 | //戻り値としてArrayList< AccountInfo >型の変数を利用 |
27 | public ArrayList< AccountInfo > selectAll(){ |
29 | Connection con = null; |
33 | ArrayList< AccountInfo > list = new ArrayList< AccountInfo >(); |
36 | String sql = "SELECT * FROM account"; |
39 | con = getConnection(); |
40 | smt = con.createStatement(); |
43 | ResultSet rs = smt.executeQuery(sql); |
47 | AccountInfo accountinfo =new AccountInfo(); |
48 | accountinfo.setId(rs.getString("id")); |
49 | accountinfo.setName(rs.getString("name")); |
50 | accountinfo.setEmail(rs.getString("email")); |
51 | accountinfo.setAuthority(rs.getString("authority")); |
52 | list.add(accountinfo); |
56 | throw new IllegalStateException(e); |
60 | try{smt.close();}catch(SQLException ignore){} |
63 | try{con.close();}catch(SQLException ignore){} |
① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch13
③ 名前 :SelectServlet1
④ スーパークラス :javax.servlet.http.HttpServlet
⑤ アクセスURL :http://localhost:8080/web_basic/SelectServlet1
➢ SelectServlet1.java
6 | import javax.servlet.http.*; |
8 | public class SelectServlet1 extends HttpServlet{ |
10 | public void doGet(HttpServletRequest request ,HttpServletResponse response) |
11 | throws ServletException ,IOException{ |
17 | ArrayList< AccountInfo > list = new ArrayList< AccountInfo >(); |
20 | AccountDao1 objDao = new AccountDao1(); |
23 | list = objDao.selectAll(); |
25 | //検索結果を持ってlist1.jspにフォワード |
26 | request.setAttribute("list", list); |
28 | }catch (IllegalStateException e) { |
29 | error ="DB接続エラーの為、一覧表示はできませんでした。"; |
32 | error ="予期せぬエラーが発生しました。< br >"+e; |
35 | request.setAttribute("error", error); |
36 | request.getRequestDispatcher("/view/ch13/list1.jsp").forward(request, response); |
➢ web.xml
2 | < servlet-name >SelectServlet1Mapping</ servlet-name > |
3 | < servlet-class >ch13.SelectServlet1</ servlet-class > |
6 | < servlet-name >SelectServlet1Mapping</ servlet-name > |
7 | < url-pattern >/SelectServlet1</ url-pattern > |
① 親フォルダの入力または選択 :web_basic/view/ch13
② ファイル名 :list1.jsp
③ アクセスURL :SelectServlet1.javaからの画面遷移でアクセスされる
➢ list1.jsp
1 | <%@page contentType="text/html; charset=UTF-8"%> |
2 | <%@page import="java.util.ArrayList,ch13.AccountInfo"%> |
5 | ArrayList< AccountInfo > list = (ArrayList< AccountInfo >)request.getAttribute("list"); |
6 | String error = (String)request.getAttribute("error"); |
11 | < title >全てのデータを表示する</ title > |
14 | < div style = "text-align:center" > |
15 | < h2 style = "text-align:center" >全てのデータを表示するプログラム</ h2 > |
16 | < hr style = "height:3; background-color:#0000FF" /> |
19 | < table style = "margin:0 auto" > |
21 | < th style = "background-color:#6666FF; width:100" >ID</ th > |
22 | < th style = "background-color:#6666FF; width:100" >名前</ th > |
23 | < th style = "background-color:#6666FF; width:250" >アドレス</ th > |
24 | < th style = "background-color:#6666FF; width:100" >権限</ th > |
28 | for(int i=0;i< list.size ();i++){ |
31 | < td style = "text-align:center; width:100" ><%= list.get(i).getId() %></ td > |
32 | < td style = "text-align:center; width:100" ><%= list.get(i).getName() %></ td > |
33 | < td style = "text-align:center; width:250" ><%= list.get(i).getEmail() %></ td > |
34 | < td style = "text-align:center; width:100" ><%= list.get(i).getAuthority() %></ td > |
解説
このプログラムは、サーブレット内でMySQLへ接続するためのDAOクラスであるAccountDao1クラスのオブジェクトを生成し、MySQLからaccountテーブル内の全てのデータを取得します。取得されたデータはArrayListクラスとAccountInfoクラスを利用して管理され、リクエストスコープを利用してJSPで一覧として表示します。
AccountDao1クラスでは、9行目から12行目で接続用の情報をフィールドに定数として定義しています。また、15行目から23行目はデータベースとの接続を行うgetConnection()メソッド、27行目から67行目ではaccountテーブルの全てのデータを検索するselectAll()メソッドが定義されています。このselectAll()の処理については、「Javaデータベース連携(JDBC)」の4.2.4項で詳しく解説していますので、ここでは省略します。
SelectServlet1.javaでは17行目でselectAll()メソッドの戻り値を格納する変数を定義しています。
17:ArrayList<AccountInfo> list = new ArrayList<AccountInfo>();
20行目でDAOクラスをオブジェクト化し、23行目でデータの取得を行なっています。
20:AccountDao1 objDao = new AccountDao1();
23:list = objDao.selectAll();
図 13.3.1: selectAll ()メソッドによるデータ取得の流れ
26行目では取得したデータをリクエストスコープへ登録してします。
26:request.setAttribute("list", list);
list1.jspでは、5行目でリクエストスコープからデータを取得します。
5:ArrayList<AccountInfo> list = (ArrayList<AccountInfo>)request.getAttribute("list");
取得されたデータは次のようにArrayListで管理されています。

図 13.3.2: リクエストスコープから取得したArrayList
取得されたデータは28行目から37行目で一覧として表示されます。
28: for(int i=0;i<list.size();i++){
29:%>
30:<tr>
31: <td style="text-align:center; width:100"><%= list.get(i).getId() %></td>
32: <td style="text-align:center; width:100"><%= list.get(i).getName() %></td>
33: <td style="text-align:center; width:250"><%= list.get(i).getEmail() %></td>
34: <td style="text-align:center; width:100"><%= list.get(i).getAuthority() %></td>
35:</tr>
36:<%
37: }
list1.jspの28行目のfor文のブロックは37行目までになっており、31行目から34行目のHTMLを繰り返し出力します。
1周目のループではArraylistの0番目の要素、2周目ではArraylistの1番目の要素からAccountInfoクラスのオブジェクトを取得し、オブジェクト内の各データをHTMLタグ内に埋め込んでいます。

図 13.3.3: for文の1周目のHTML内へデータの埋め込み
このループ処理をデータの数だけ繰り返すことで一覧として表示します。

図 13.3.4: ループ処理で生成される画面
このように、Webアプリケーション上からJDBCを利用して取得したデータを、ループ処理によって一覧として表示することが可能です。
また、このプログラムではDAOクラス内でエラーが発生した場合に、catch内の処理で「IllegalStateException」を意図的に発生させて呼び出し元のサーブレットへ例外が発生したことを伝えています。
55:}catch(Exception e){
56: throw new IllegalStateException(e);
56行目の「throw」キーワードが、throwの後ろに書かれた例外クラスのオブジェクトを呼び出し元に投げる処理を行なっています。その結果、例外クラスのオブジェクトをサーブレットでcatchし、エラーメッセージを作成、エラー画面に遷移することができます。
DAOクラスのエラー処理内に「throw」が無い場合には、エラーが発生していても、このメソッドの呼び出し元のサーブレットで例外をcatchできません。そのため、サーブレットが処理を継続してしまうことになりますので注意してください。
なお、このプログラムのDAOクラス内では例外として「ClassNotFoundException」や「SQLException」が発生します。どの例外が発生した場合でも、DAOクラスが利用できない不正または不適切な状態でメソッドが呼び出されたものとして、発生した例外は全て「IllegalStateException」をサーブレットへ返すように記述しています。
この「IllegalStateException」をサーブレットへ返す処理は当スクール独自の処理であることに注意してください。「IllegalStateException」が必ず必要なわけではなく、状況によっては別の例外クラスのオブジェクトを返したり、例外クラスのオブジェクトをサーブレットへ返さないという方法も考えられます。
13.3.2 絞り込み検索を行いデータを表示する
一覧画面でデータベースのデータを全て表示してしまうと、必要なデータを見つけるのが困難になります。そのような場合は、範囲検索やあいまい検索などのSQL文を発行し、表示するデータを制限します。
絞り込み検索を行いデータを表示するプログラム
入力フォームからIDに含まれる文字列を入力し、該当するデータをWebブラウザに表示します。
実行結果

アプリケーション構成

① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch13
③ 名前 :AccountDao2
➢ AccountDao2.java
6 | public class AccountDao2 { |
9 | private static String RDB_DRIVE = "com.mysql.jdbc.Driver"; |
10 | private static String URL = "jdbc:mysql://localhost/accountdb"; |
11 | private static String USER = "root"; |
12 | private static String PASS = "root123"; |
15 | public static Connection getConnection(){ |
17 | Class.forName(RDB_DRIVE); |
18 | Connection con = DriverManager.getConnection(URL, USER, PASS); |
21 | throw new IllegalStateException(e); |
25 | //データベースから全てのアカウント情報の検索を行うメソッド |
26 | public ArrayList< AccountInfo > search(String id){ |
28 | Connection con = null; |
32 | ArrayList< AccountInfo > list = new ArrayList< AccountInfo >(); |
35 | String sql = "SELECT * FROM account WHERE id LIKE '%" + id + "%'"; |
38 | con = getConnection(); |
39 | smt = con.createStatement(); |
42 | ResultSet rs = smt.executeQuery(sql); |
46 | AccountInfo accountinfo =new AccountInfo(); |
47 | accountinfo.setId(rs.getString("id")); |
48 | accountinfo.setName(rs.getString("name")); |
49 | accountinfo.setEmail(rs.getString("email")); |
50 | accountinfo.setAuthority(rs.getString("authority")); |
51 | list.add(accountinfo); |
55 | throw new IllegalStateException(e); |
59 | try{smt.close();}catch(SQLException ignore){} |
62 | try{con.close();}catch(SQLException ignore){} |
① 親フォルダの入力または選択 :web_basic/view/ch13
② ファイル名 :searchForm.jsp
③ アクセスURL :http://localhost:8080/web_basic/view/ch13/searchForm.jsp
➢ searchForm.jsp
1 | <%@page contentType="text/html; charset=UTF-8"%> |
5 | < title >絞込みデータを表示する</ title > |
8 | < div style = "text-align:center" > |
9 | < h2 style = "text-align:center" >検索ID入力画面</ h2 > |
10 | < hr style = "height:3; background-color:#0000ff" /> |
13 | < form action="<%=request.getContextPath() %>/SelectServlet2"> |
14 | < input type = "text" name = "id" > |
15 | < input type = "submit" value = "検索" > |
① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch13
③ 名前 :SelectServlet2
④ スーパークラス :javax.servlet.http.HttpServlet
⑤ アクセスURL :searchForm.jspからの画面遷移でアクセスされる
➢ SelectServlet2.java
6 | import javax.servlet.http.*; |
8 | public class SelectServlet2 extends HttpServlet{ |
10 | public void doGet(HttpServletRequest request ,HttpServletResponse response) |
11 | throws ServletException ,IOException{ |
17 | String id = request.getParameter("id"); |
20 | ArrayList< AccountInfo > list = new ArrayList< AccountInfo >(); |
23 | AccountDao2 objDao2 = new AccountDao2(); |
26 | list = objDao2.search(id); |
28 | //検索結果を持ってlist2.jspにフォワード |
29 | request.setAttribute("list", list); |
31 | }catch (IllegalStateException e) { |
32 | error ="DB接続エラーの為、一覧表示はできませんでした。"; |
35 | error ="予期せぬエラーが発生しました。< br >"+e; |
38 | request.setAttribute("error", error); |
39 | request.getRequestDispatcher("/view/ch13/list2.jsp").forward(request, response); |
➢ web.xml
2 | < servlet-name >SelectServlet2Mapping</ servlet-name > |
3 | < servlet-class >ch13.SelectServlet2</ servlet-class > |
6 | < servlet-name >SelectServlet2Mapping</ servlet-name > |
7 | < url-pattern >/SelectServlet2</ url-pattern > |
① 親フォルダの入力または選択 :web_basic/view/ch13
② ファイル名 :list2.jsp
③ アクセスURL :SelectServlet2.javaからの画面遷移でアクセスされる
➢ list2.jsp
1 | <%@page contentType="text/html; charset=UTF-8"%> |
2 | <%@page import="java.util.ArrayList,ch13.AccountInfo"%> |
4 | ArrayList< AccountInfo > list = (ArrayList< AccountInfo >)request.getAttribute("list"); |
5 | String error = (String)request.getAttribute("error"); |
9 | < title >絞込みデータを表示する</ title > |
12 | < div style = "text-align:center" > |
13 | < h2 style = "text-align:center" >絞込みデータを表示する</ h2 > |
14 | < hr style = "height:3; background-color:#0000ff" /> |
17 | < table style = "margin:0 auto" > |
19 | < th style = "background-color:#6666FF; width:100" >ID</ th > |
20 | < th style = "background-color:#6666FF; width:100" >名前</ th > |
21 | < th style = "background-color:#6666FF; width:250" >アドレス</ th > |
22 | < th style = "background-color:#6666FF; width:100" >権限</ th > |
26 | for(int i=0;i< list.size ();i++){ |
29 | < td style = "text-align:center; width:100" > |
30 | < A href="<%=request.getContextPath() %>/SelectServlet3?id=<%=list.get(i).getId()%>"> |
31 | <%= list.get(i).getId() %></ A > |
33 | < td style = "text-align:center; width:100" ><%= list.get(i).getName() %></ td > |
34 | < td style = "text-align:center; width:250" ><%= list.get(i).getEmail() %></ td > |
35 | < td style = "text-align:center; width:100" ><%= list.get(i).getAuthority() %></ td > |
解説
このプログラムは入力フォームから入力された検索文字列を利用し、DAOクラス内であいまい検索を行なっています。
35:String sql = "SELECT * FROM account WHERE id LIKE '%" + id + "%'";
あいまい検索によって取得されたデータは、一覧を表示するプログラムと同じように、DAOクラスからサーブレット、JSPへ渡され画面に一覧表示されます。
このように、一覧機能を持ったプログラムでは、検索機能を実装することでユーザインタフェースの向上を図ることができます。
なお、list2.jspの30行目に記述されたリンクは次の項で利用します。そのため、このプログラムを作成した時点では、リンク切れとなりますが、問題ありません。
30:<A href="<%=request.getContextPath() %>/SelectServlet3?id=<%=list.get(i).getId()%>">
13.3.3 1件のデータを検索し表示する
複数のデータを取得する場合、ループ文を利用してDTOクラスのオブジェクトをArrayListへ格納する処理を行うことで、データベースから取得したデータを管理しました。しかし、1件のみ表示したい場合などには、ArrayListへ格納する処理を行うと効率がよくありません。そのような場合は、DTOクラスのオブジェクトのみを利用してデータを管理します。
1件のデータを検索し表示するプログラム
前項13.3.2で作成した画面をクリックすることで、選択されたIDの詳細な情報をWebブラウザに表示します。
このプログラムでは、データベースから取得されるデータは1件です。そのため、DTOクラスのみを利用してデータを保持します。
実行結果

アプリケーション構成

① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch13
③ 名前 :AccountDao3
➢ AccountDao3.java
5 | public class AccountDao3 { |
8 | private static String RDB_DRIVE = "com.mysql.jdbc.Driver"; |
9 | private static String URL = "jdbc:mysql://localhost/accountdb"; |
10 | private static String USER = "root"; |
11 | private static String PASS = "root123"; |
14 | public static Connection getConnection(){ |
16 | Class.forName(RDB_DRIVE); |
17 | Connection con = DriverManager.getConnection(URL, USER, PASS); |
20 | throw new IllegalStateException(e); |
23 | //データベースから指定された1件のアカウント情報の検索を行うメソッド |
24 | public AccountInfo selectById(String id){ |
26 | Connection con = null; |
30 | AccountInfo accountinfo =new AccountInfo(); |
33 | String sql = "SELECT * FROM account WHERE id = '" + id + "'"; |
36 | con = getConnection(); |
37 | smt = con.createStatement(); |
40 | ResultSet rs = smt.executeQuery(sql); |
44 | accountinfo.setId(rs.getString("id")); |
45 | accountinfo.setName(rs.getString("name")); |
46 | accountinfo.setEmail(rs.getString("email")); |
47 | accountinfo.setAuthority(rs.getString("authority")); |
50 | throw new IllegalStateException(e); |
54 | try{smt.close();}catch(SQLException ignore){} |
57 | try{con.close();}catch(SQLException ignore){} |
① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch13
③ 名前 :SelectServlet3
④ スーパークラス :javax.servlet.http.HttpServlet
⑤ アクセスURL :list2.jspからの画面遷移でアクセスされる
➢ SelectServlet3.java
5 | import javax.servlet.http.*; |
7 | public class SelectServlet3 extends HttpServlet{ |
9 | public void doGet(HttpServletRequest request ,HttpServletResponse response) |
10 | throws ServletException ,IOException{ |
16 | String id = request.getParameter("id"); |
19 | AccountInfo account = new AccountInfo(); |
22 | AccountDao3 objDao3 = new AccountDao3(); |
25 | account = objDao3.selectById(id); |
27 | //検索結果を持ってlist3.jspにフォワード |
28 | request.setAttribute("account", account); |
30 | }catch (IllegalStateException e) { |
31 | error ="DB接続エラーの為、一覧表示はできませんでした。"; |
34 | error ="予期せぬエラーが発生しました。< br >"+e; |
37 | request.setAttribute("error", error); |
38 | request.getRequestDispatcher("/view/ch13/list3.jsp").forward(request, response); |
➢ web.xml
2 | < servlet-name >SelectServlet3Mapping</ servlet-name > |
3 | < servlet-class >ch13.SelectServlet3</ servlet-class > |
6 | < servlet-name >SelectServlet3Mapping</ servlet-name > |
7 | < url-pattern >/SelectServlet3</ url-pattern > |
① 親フォルダの入力または選択 :web_basic/view/ch13
② ファイル名 :list3.jsp
③ アクセスURL :SelectServlet3.javaからの画面遷移でアクセスされる
➢ list3.jsp
1 | <%@page contentType="text/html; charset=UTF-8"%> |
2 | <%@page import="ch13.AccountInfo"%> |
4 | AccountInfo account = (AccountInfo)request.getAttribute("account"); |
5 | String error = (String)request.getAttribute("error"); |
9 | < title >1件のデータを表示する</ title > |
12 | < div style = "text-align:center" > |
13 | < h2 style = "text-align:center" >1件のデータを表示するプログラム</ h2 > |
14 | < hr style = "height:3; background-color:#0000ff" /> |
17 | < table style = "margin:0 auto" > |
19 | < th style = "background-color:#6666FF; width:100" >ID</ th > |
20 | < th style = "background-color:#6666FF; width:100" >名前</ th > |
21 | < th style = "background-color:#6666FF; width:250" >アドレス</ th > |
22 | < th style = "background-color:#6666FF; width:100" >権限</ th > |
28 | < td style = "text-align:center; width:100" ><%= account.getId() %></ td > |
29 | < td style = "text-align:center; width:100" ><%= account.getName() %></ td > |
30 | < td style = "text-align:center; width:250" ><%= account.getEmail() %></ td > |
31 | < td style = "text-align:center; width:100" ><%= account.getAuthority() %></ td > |
解説
このプログラムでは、前項13.3.2で作成した画面のID部分のリンクをクリックすることで、選択されたIDのみの情報を表示する画面に遷移します。このサンプルでは、IDに対する情報量は1件のデータを表示する画面と絞り込みした一覧情報を表示する画面とで変わりはありません。一覧に表示する必要のない細かな情報を表示するための画面と思って頂ければ結構です。
データベースからデータを取得し、画面に表示するという大きなプログラムの流れは前項13.3.1で作成したプログラムと変わりませんが、データを保持する方法が若干異なります。
このプログラムはlist1.jspでクリックされたIDの1件分のデータのみを表示する画面です。MySQLから取得されるデータは必ず1行分のデータになるため、データベースから取得された値を管理する変数はArrayListクラスを利用せず、AccountDao3.javaの30行目やSelectServlet3.javaの19行目のように、AccountInfoクラスのみで生成されています。
30: AccountInfo accountinfo = new AccountInfo ();
このように、データベースから取得するデータが必ず1件になるような場合には、ArrayListクラスなどを利用せずに、データの管理を行うこともできます。
NEXT>> 13.4 データの登録