こんにちは、大学時代にプログラミングを始め、現在はエンジニアをしているuhablog(ウハブログ)です。
現在Java(サーブレット・jsp) x PostgreSQLを使ってTodoアプリを作成しています。現時点での機能は次のとおりです。
今回は上記に加えてTodoの編集を行えるようにしていきます。
今回作成する編集機能は次のような流れにします。
- 一覧から「Todoを編集する」ボタンをクリックしたら編集画面に遷移
- 編集画面にはすでに入力されているデータが入っている上で編集をすることができる
- 編集が終了し、「Todoを更新する」を押すとデータベースに編集内容が反映される
- 一覧表示するとTodoの内容が更新されている
挫折せずにプログラミングを学ぶために必要なこと
僕はプログラミングで挫折した経験があります。
それは周りに聞ける人がいなく、一人でエラーと戦っていたからです。
Freeksは月額10,780円という破格の値段で、現役エンジニアに質問する環境を手に入れることができるプログラミングスクールです。
次のような悩みを少しでも抱えていたら、まずは無料カウンセリングを受けてみてください。
申込みは1分でできます。学習する環境にお金を使うというのは良い自己投資になります。
>>Freeksの無料カウンセリングはこちら
list.jspの変更
まずは一覧から編集画面に遷移するためにlist.jspを編集します。
考慮する点は次の2点です。
- Todoを取得するためにTodoのIDをサーバーに送る必要がある
- 「Todoを更新する」を押したら更新画面に遷移する
今回はlist.jspにaタグを設置します。
リンクで更新処理をするサーブレットにリクエストを送ります。
その際にリクエストパラメータとしてTodoのIDを送るようにします。
リンクで送られるリクエストは基本的にGETメソッドです。
GETメソッド時はURLに記述することでパラメータを送ることができます。
現在for文を使ってTodoを表示していますが、その中身を次のように変更します。
<h5><%=todo.getTodo()%></h5>
<h6><%=todo.getTimeLimit()%></h6>
<a href="update-servlet?<%=Parameters.TODO_ID %>=<%= todo.getId() %>">todoを更新する</a>
重要なのはaタグのhref属性です。
最初の「update-servlet」はリクエストを送りたいサーブレットのパスです。これは後ほど作成します。
次に「?<%=Parameters.TODO_ID %>=<%= todo.getId() %>」となっているところです。
GETでリクエストを送るときは「?x=y」とすることでキーがx、値がyという情報をサーバー側に送ることができます。
今回はまず前回作成したパラメータ名をstatic変数で準備したクラスを使ってtodoIdというキーで値を送ります。
実際に送られる値が「todo.getId()」によって取得できる値になります。
この変更によって一覧画面に「todoを更新する」リンクが表示され、それをクリックすると更新したいTodoのidがサーバー側に送られるという事になります。
次にそのリクエストを受け取るサーバー側の処理を記述していきます。
UpdateDAOの作成
まずは更新機能でデータベースに接続する際に利用するUpdateDAOクラスをmodelパッケージ内に作成します。
更新機能でデータベースに接続したいのは「更新するTodoを取得する」処理と「実際にTodoを更新する」処理が必要です。
まずは「更新するTodoを取得する」メソッドを作成します。中身は次のようになります。
package model;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import model.dao.dto.TodoDTO;
// Todoの更新を行うクラス
public class UpdateDAO {
/**
* idを元にデータベースからTodo情報を取得する
* @param id
* @return todo
* @throws SQLException
* @throws ClassNotFoundException
*/
public TodoDTO getTodo(int id) throws SQLException, ClassNotFoundException {
// 取得したTodoを格納する変数
TodoDTO todo = new TodoDTO();
// Idを指定してTodoを取得するSQL
String sql = "SELECT id, todo, timeLimit FROM todo where id = ? ";
// DBに接続し、Todoを取得する
try (Connection con = DBConnection.getConnection();
PreparedStatement pstmt = con.prepareStatement(sql);) {
pstmt.setInt(1, id);
// SQLを実行しTodoを取得する
ResultSet res = pstmt.executeQuery();
while(res.next()) {
// DBから取得したTodoの情報をtodoに持たせる
todo.setId(res.getInt("id"));
todo.setTodo(res.getString("todo"));
todo.setTimeLimit(res.getDate("timeLimit"));
}
}
return todo;
}
}
大切なのはgetTodoメソッドです。
更新するTodoのidを受け取り、それを元にデータベースからTodoのデータを取得します。
getTodoメソッドの中身を見ていきます。
まずは実行するSQL文を作成しています。最後の「?」の中に引数で受け取ったidを設定します。
// Idを指定してTodoを取得するSQL
String sql = "SELECT id, todo, timeLimit FROM todo where id = ? ";
次に実際にSQLを実行しTodoの情報を取得します。
最初にSQLにIdを設定します。
その後executeQueryメソッドでSQLを実行します。
取得したTodoの情報をtodoDTOに設定して値を持たせます。
// DBに接続し、Todoを取得する
try (Connection con = DBConnection.getConnection();
PreparedStatement pstmt = con.prepareStatement(sql);) {
pstmt.setInt(1, id);
// SQLを実行しTodoを取得する
ResultSet res = pstmt.executeQuery();
while(res.next()) {
// DBから取得したTodoの情報をtodoに持たせる
todo.setId(res.getInt("id"));
todo.setTodo(res.getString("todo"));
todo.setTimeLimit(res.getDate("timeLimit"));
}
}
これでidを元に更新対象となるTodoのデータを取得することができます。
UpdateServletの作成
次にサーブレットを作成します。
servletパッケージの中にUpdateServlet.javaを作成します。
パスは次のように設定します。
@WebServlet("/update-servlet")
一覧画面からaタグのリンクを使ってリクエストが送られてきます。
これはGETメソッドでのリクエストなのでサーブレット内のdoGetメソッドを編集します。
/**
* リクエストパラメータから送られてきたTodoのIDをもとにDBからデータを取得し、画面に表示する
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// リクエストパラメータからtodoIdを取得する
int todoId = Integer.parseInt(request.getParameter(Parameters.TODO_ID));
UpdateDAO dao = new UpdateDAO();
TodoDTO todo = new TodoDTO();
try {
// todoの取得
todo = dao.getTodo(todoId);
} catch (SQLException | ClassNotFoundException e ) {
e.printStackTrace();
}
request.setAttribute("todo", todo);
request.getRequestDispatcher("update.jsp").forward(request, response);
}
最初にリクエストパラメータからTodoのIdを取得します。
取得する際にはParametersクラスのstatic変数を使っています。
// リクエストパラメータからtodoIdを取得する
int todoId = Integer.parseInt(request.getParameter(Parameters.TODO_ID)
Todo情報を取得するための変数宣言です。
先程作したUpdateDAOとTodoDTOをインスタンス化しておきます。
UpdateDAO dao = new UpdateDAO();
TodoDTO todo = new TodoDTO();
上記で宣言した変数を使ってデータベースに接続してTodo情報を取得します。
try {
// todoの取得
todo = dao.getTodo(todoId);
} catch (SQLException | ClassNotFoundException e ) {
e.printStackTrace();
}
取得したTodoの情報をリクエストスコープに設定します。
リクエストスコープに関してはQiitaにまとまった記事があるので時間がある方は読んでみると理解が深まります。
そしてupdate.jspに画面遷移します。
request.setAttribute("todo", todo);
request.getRequestDispatcher("update.jsp").forward(request, response);
update.jsp
Todoを編集する画面であるupdate.jspを作成します。全体は以下のようになります。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="model.dao.dto.TodoDTO" %>
<%@ page import="constant.Parameters" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<%
TodoDTO todo = (TodoDTO)request.getAttribute("todo");
%>
<body>
<form action="update-servlet" method="post" >
<label>Todo: </label><input type="text" name="<%=Parameters.TODO %>" value="<%=todo.getTodo()%>"><br>
<label>Limit: </label><input type="date" name="<%=Parameters.TIME_LIMIT %>" value="<%=todo.getTimeLimit()%>"> <br>
<input type="hidden" name="<%=Parameters.TODO_ID %>" value="<%=todo.getId() %>">
<input type="submit" value="Todoを更新する">
</form>
</body>
</html>
まずUpdateServlet内でリクエストスコープに設定したtodo情報を取得します。
<%
TodoDTO todo = (TodoDTO)request.getAttribute("todo");
%>
更新するTodoを画面に表示するのが以下の箇所です。大切なのは上二つのinputタグの中です。
<form action="update-servlet" method="post" >
<label>Todo: </label><input type="text" name="<%=Parameters.TODO %>" value="<%=todo.getTodo()%>"><br>
<label>Limit: </label><input type="date" name="<%=Parameters.TIME_LIMIT %>" value="<%=todo.getTimeLimit()%>"> <br>
<input type="hidden" name="<%=Parameters.TODO_ID %>" value="<%=todo.getId() %>">
<input type="submit" value="Todoを更新する">
</form>
既存の情報を入力された状態で表示したいのでinputタグのvalue属性にtodoの情報を入れています。
また更新する際にサーバー側にデータを送りたいのでname属性の中をParametersクラスのstatic変数を使って名前を決めています。
<input type="text" name="<%=Parameters.TODO %>" value="<%=todo.getTodo()%>">
<input type="date" name="<%=Parameters.TIME_LIMIT %>" value="<%=todo.getTimeLimit()%>">
動作確認
一旦ここまでで動作確認してみます。サーバーを立ち上げ一覧画面を表示します。
一部切り取っていますが、下記のような画面が表示されていれば良いです。
「todoを更新する」リンクがあることを確認しましょう
「todoを更新する」リンクを押してみます。
今回は「create todo app」「2021-06-30」のTodoのリンクを押してみます。
すると以下の画面のように既存のデータが入力された状態の入力画面が表示されます。
挫折せずにプログラミングを学ぶためには?
挫折せずにプログラミングを学ぶために必要なこと
僕はプログラミングで挫折した経験があります。
それは周りに聞ける人がいなく、一人でエラーと戦っていたからです。
Freeksは月額10,780円という破格の値段で、現役エンジニアに質問する環境を手に入れることができるプログラミングスクールです。
次のような悩みを少しでも抱えていたら、まずは無料カウンセリングを受けてみてください。
申込みは1分でできます。学習する環境にお金を使うというのは良い自己投資になります。
>>Freeksの無料カウンセリングはこちら
【関連記事】Freeks評判、口コミ