【Javaサーブレット&jsp入門#3】Select文を実行してPostgreSQLからデータを取得して一覧表示する

Java

今回の記事はこちらの記事の続きとなっております。
サーブレットとjspを使ってTodoWebアプリケーションを作成します。
今回は実際にテーブルからデータを取得してWebブラウザ上で一覧表示してみます。

今回作るものの流れを説明すると、home.htmlにformを作成します。
そこからListServletにリクエストを送ります。ListServletではリクエストを受け取って、データベースへ接続しデータを取得します。
そのデータを扱いやすい形に整えてlist.jspでデータを表示します。

その他の機能はこちらにまとめています。
ご質問等あればこちらのTwitterアカウントまでお願いします。

Udemyの動画講座でわかりやすくサーブレットを勉強するicon

home.html

最初の画面になります。非常にシンプルな作りです。<h1>タグを使ったタイトルを表示します。formによって「Todo一覧を表示」と書かれたボタンを表示します。
これが押されるとactionに指定したlist-servletに処理が移ります。
リクエスト方法はgetとします。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
	<h1>Todo 管理Webアプリケーション</h1>
	<form action="list-servlet" method="get">
		<input type="submit" value="Todo一覧を表示">
	</form>

</body>
</html>

TodoListDAOの作成

実際にPostgreSQLに接続し、Todoの一覧を取得するメソッドを持つクラスを作成します。
model.daoパッケージの中にTodoListDAO.javaを作成します。中身は次のようにします。

package model.dao;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import model.DBConnection;
import model.dao.dto.TodoDTO;

/**
 * Todoの一覧を取得するクラス
 *
 * @author yuhablog
 */
public class TodoListDAO {

	/**
	 * Todoの一覧を取得する
	 * @return todoの一覧
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public List<TodoDTO> getTodoList() throws ClassNotFoundException, SQLException {
		// 返却用Listの初期化
		List<TodoDTO> todoList = new ArrayList<>();

		// 実行するSQL
		String sql = "SELECT id, todo, timeLimit from todo";

		// DBに接続し、Todo一覧を取得する
		try (Connection con = DBConnection.getConnection();
				PreparedStatement pstmt = con.prepareStatement(sql)) {

			// SQLを実行しResultSetの変数に結果を格納する
			ResultSet res = pstmt.executeQuery();
			// 実行結果を順番に取り出す
			while (res.next()) {
			        //  それぞれid, todo, timeLimitを取得する
				int id = res.getInt("id");
				String todo = res.getString("todo");
				Date timeLimit = res.getDate("timeLimit");

				// 取得したid, todo, timeLimitでTodoDTOを初期化してListに追加
				todoList.add(new TodoDTO(id, todo, timeLimit));
			}
		}

		return todoList;
	}
}

大切なのはtry文の中になります。
まずPostgreSQLへの接続を取得するために前回の記事↗︎で作成したgetConnectionメソッドを呼び出します。
次にString型のSQLを実際にPostgreSQLで実行するためにprepareStatementメソッドに引数としてsqlを渡します。
これらを行っているのが、try直後の()内の処理です。

そして実際にSQLの実行を行うのが次の記述です。
今回はSELECT文を実行しているので、ResultSet型の変数を用意して結果を受け取ります。
この変数resの中にSELECT文の実行によって取得できたデータが格納されます。

// SQLを実行しResultSetの変数に結果を格納する
ResultSet res = pstmt.executeQuery();

さらに次の記述でSELECTによって取得したデータを返却用の変数todoListに追加していきます。
結果が格納されたresに対して様々なメソッドを呼び出します。
nextメソッドで次にデータがある場合はwhile内の処理が実行されます。
res.getXXXメソッドで引数で指定したカラムの値を取り出せます。
XXXの部分をデータ型に合わせて変更していきます。
取得したデータを前回↗︎作成したTodoDTOのコンストラクタに渡して、それをtodoListに追加します。PostgreSQLから取得したTodoを全てtodoListに追加し終わるとwhileループを抜けます。

// 実行結果を順番に取り出す
while (res.next()) {
	//  それぞれid, todo, timeLimitを取得する
	int id = res.getInt("id");
	String todo = res.getString("todo");
	Date timeLimit = res.getDate("timeLimit");

	// 取得したid, todo, timeLimitでTodoDTOを初期化してListに追加
	todoList.add(new TodoDTO(id, todo, timeLimit));
}

PostgreSQLからSelectするListServlet

home.htmlから送られてくるリクエストを元にPostgreSQLからtodoの一覧を取得し、結果を表示するための処理を記述したListServletを作成します。

まずはサーブレットを作ります。
srcフォルダの中にservletというパッケージを作成してください。
その後右クリックをして新規→その他を選択します。

次にWebのなかにあるサーブレットを選択します。

クラス名をListServletと入力して次へを押します。そのまま進んで完了を押します。

すると新しくListServlet.javaが作られます。
この13行目の@WebServletのなかの(“/ListServlet”)を(“/list-servlet”)に変更します。
これは先ほど作ったhome.htmlのformタグのactionでlist-servletにリクエストが投げられるように設定したからです。

そして28行目あたりからdoGetメソッドが書かれているはずです。
先ほどのformでメソッドをgetにしたためformが提出されるとdoGetメソッドが実行されます。
formのなかのメソッドをPOSTにしていた場合は36行目からのdoPostメソッドが実行されます。

今回作るdoGetメソッドの中身は以下のようになります。順番に解説していきます。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// todoの一覧を保持する変数を宣言
		List<TodoDTO> todoList = new ArrayList<>();

		// DAOを生成し、Todo一覧を取得する
		TodoListDAO dao = new TodoListDAO();
		try {
			// todo一覧を取得する
			todoList = dao.getTodoList();
		}catch(SQLException | ClassNotFoundException e) {
			e.printStackTrace();
		}

		// todo一覧をリクエストスコープに設定する
		request.setAttribute("todoList", todoList);
		// todo一覧画面に遷移する
		RequestDispatcher rd = request.getRequestDispatcher("list.jsp");
		rd.forward(request, response);
}

まずは先ほど作成したDAOをインスタンス化し、getTodoListメソッドを呼び出します。
戻り値をTodoDOTのListであるtodoListに格納します。

// DAOを生成し、Todo一覧を取得する
TodoListDAO dao = new TodoListDAO();
try {
	// todo一覧を取得する
	todoList = dao.getTodoList();
}catch(SQLException | ClassNotFoundException e) {
	e.printStackTrace();
}

次に取得したtodo一覧をjsp側でも扱えるようにしたいのでリクエストスコープにtodoListを設定します。
このスコープという概念はJavaでWebアプリを作成する上で非常に重要な概念になります。

リクエストスコープは1リクエスト毎に生成されます。
簡単に説明すると1回のリクエストの間だけ使えるデータの保存場所みたいなノリです。
Qiitaにまとまった記事があるので時間がある方は読んでみると理解が深まります。

// todo一覧をリクエストスコープに設定する
request.setAttribute("todoList", todoList);

request.getRequestDispatcherによって次にどこに処理を移すか指示しています。
引数でlist.jspを指定したのでfowardメソッドを使うことで指定したURLに処理を移すことができます。

RequestDispatcher rd = request.getRequestDispatcher("list.jsp");
rd.forward(request, response);

list.jsp

サーブレットからforwardされてlist.jspに処理が移ります。
全体のコードは次のようになります。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.List, java.util.ArrayList, model.dao.dtoTodoDTO"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Todo List</title>
</head>
<body>
	<%
		List<TodoDTO> todoList = (List) request.getAttribute("todoList");
	%>

	<% for(TodoDTO todo: todoList){  %>
		<%=todo.getTodo() %> 期限:<%=todo.getTimeLimit() %><br>
	<% } %>


</body>
</html>

まずこのjsp内でもListを使いたいので一番初めにインポートします。
またTodoDOTも利用するのでこちらも合わせてインポートしておきます。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.List, java.util.ArrayList, model.dao.dtoTodoDTO"%>

bodyタグの中身です。
まずは先ほどのサーブレットで作成したtodoListを取り出します。jspでは<%%>の間にJavaのコードを記述することができます。

requestのgetAttributeメソッドを使うことでリクエストスコープからデータの取得を行うことができます。
先ほどサーブレットでリクエストスコープにtodoListを設定したので、これをjspで取り出すことができます。
getAttributeの引数はsetAttributeしたときの第一引数と一致している必要があります。

<%
	List<TodoDTO> todoList = (List) request.getAttribute("todoList");
%>

for文でtodoListの要素を一つづつ取り出して表示していきます。
非常に読みにくいですが、先ほどと同じく<%%>の間にJavaのコードが記述されています。
<%=todo.getTodo() %>のところにはtodo.getTodo()の戻り値が表示されるようになります。

<% for(TodoDTO todo: todoList){ %>
    <%=todo.getTodo() %> 期限:<%=todo.getTimeLimit() %><br>
<% } %>



動作確認

ここまでコードがかけたら実際にサーバーを起動してWebブラウザで確認してみます。
home.htmlを右クリックして「実行」→「サーバで実行」を選択します。

サーバを選択し、完了をクリックします。
するとコンソールに何やら文字がいっぱい出てきた後自動でWebブラウザが立ち上がります。

おそらく下記画像のようなページが出てきます。

「Todo一覧を表示」ボタンを押すと画面遷移して下記のような感じでデータベースに保存してあったデータが取り出され表示されます。
CSSを書いていないのでなんとも物寂しい見てくれですが、そこは追々整えていけばいいでしょう。

エラー対応

この記事を参考にTodoアプリを作成していただいている方からDBに接続できないエラーが発生するとのご指摘をいただきました。
ここで動作確認を行った際にClassNotFoundExceptionが発生した場合にはプロジェクト内のWEB-INF/libフォルダの中にjdbcドライバを格納してください。

質問していただいた方ありがとうございます。
他にも質問ある方いらしたらお気軽にこちらのツイッターアカウントまでお願いいたします。

次回予告

次回はTodoを登録する機能を作成します。

ご質問等あればこちらのTwitterアカウントまでお願いします。

私はプログラミング学習はオンライン動画学習サービスのUdemyで行うのが
圧倒的におすすめです。
Udemyでは

  • 動画で好きな時間・隙間時間に学べる
  • 一流のエンジニアから教えてもらえる
  • 好きな技術を体系的に学べる
  • 実際に手を動かしながら学ぶことができる
  • セール時であれば1500円〜2000円ほどで購入できる(大半の技術書より安い)
  • 講座自体がアップデートされていくので情報が古くなりにくい

Udemyにはサーブレットを学べる講座iconもあります。
「これからサーブレットを学んでJavaでWebアプリケーションを作れるようになりたい!」という方はチェックしてみてください

タイトルとURLをコピーしました