Java Java Todo Webアプリ開発

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

ウハブログ

こんにちは、大学時代にプログラミングを始め、現在はエンジニアをしているuhablog(ウハブログ)です。

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

今回は

  • home.htmlにformを作成しListServletにリクエストを送る
  • ListServletでリクエストを受け取り、データベースからデータを取得
  • list.jspでデータを表示

という流れで開発を進めていきます。

\\現役エンジニアに質問できる//

月額制スクールFreeks公式サイトはこちら

まずは無料カウンセリングから

home.html

最初の画面になります。非常にシンプルな作りです。

<h1>タグを使ったタイトルを表示します。

formによって「Todo一覧を表示」と書かれたボタンを表示します。
これが押されるとactionに指定したlist-servletに処理が移ります。

<!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;
    }
}

データベースへの接続

前回の記事↗︎で作成したgetConnectionメソッドを呼び出してPostgreSQLへの接続を取得します。

次にString型のSQLを実際にPostgreSQLで実行するためにprepareStatementメソッドに引数としてsqlを渡します。

これらを行っているのが、try直後の()内の処理です。

try (Connection con = DBConnection.getConnection();
    PreparedStatement pstmt = con.prepareStatement(sql))

SQLの実行

そして実際に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が作られます。

リクエスト先の設定

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

doGetメソッドの中を編集

そして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メソッドを呼び出します。
戻り値をTodoDTOの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を使いたいので一番初めにインポートします。
またTodoDTOも利用するのでこちらも合わせてインポートしておきます。

<%@ 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を登録する機能を作成します。

ToDoを新規作成する

独学が辛いあなたへ

プログラミング学習にはエラーやわからないところというのはつきものです。

人に聞けば5分でわかることも、自分一人で悩んでいると1日数日時間を費やしてしまうこともあります。

そんな時にプログラミングスクールであれば、質問できる環境を手に入れることができます。

Freeksはいつでもどこでも豊富なカリキュラムを学ぶことができる月額制のプログラミングスクールです。

Freeksでは無料体験を行なっているので、質問できる環境を手に入れて、プログラミング学習を挫折することなく続けていきたいという方は無料体験に参加してみてください。

Freeks公式サイトはこちら>>>

【関連記事】Freeks評判、口コミ

他のプログラミングスクール

月額10,780円のサブスク型プログラミングスクール!
>>Freeks公式サイト
20代におすすめ!無料で未経験からプログラマー就職まで実現できる!
>>ProgrammerCollege公式サイト
パーソナルメンターがつく充実したサポート
>>DMM WEBCAMP公式サイト

おすすめのプログラミングスクールについて詳しく知りたいという方はこちらの記事も参考にしてみてください。

-Java, Java Todo Webアプリ開発
-, , , , ,