エンジニア大学ではSpring Bootで簡単なWebアプリを開発する方法を発信しています。
Javaの基礎学習が終わった方へ
・Spring BootでWebアプリを開発する
・バリデーションチェックの実装・・・・・・前回の記事
・GitHubに全コード上がっています!
今回の記事ではSpring Bootで既にデータベースに存在しているデータの更新処理を実装します。
この記事を読むことで
- 指定したidのデータを取得する方法
- 指定したidのデータを更新する方法
を学ぶことができます!
bookList.html
まずは一覧画面の編集を行います。
一覧画面の記事はこちら
一覧画面では本のデータに加えて、「編集」リンクを新しく追加します。
次のようにhref属性を指定することで、「/book-edit?id=xx」というようなリクエストを送信することができます。
このidを使って、対象のデータに対して、更新処理を行なっていきます。
<a class="btn btn-success" th:href="@{/book-edit(id=*{id})}">編集</a>
「bookList.html」全体は次のようになります。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>本の一覧表示</title>
<link rel="stylesheet" th:href="@{/webjars/bootstrap/5.2.2/css/bootstrap.min.css}"/>
</head>
<body>
<div th:replace="share::header"></div>
<div class="container">
<div class="row">
<div th:each="book : ${bookList}" th:object="${book}" class="card col-3 me-2 mb-2" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title" th:text="*{title}"></h5>
<p class="card-text" th:text="*{price} + 円"></p>
<a class="btn btn-success" th:href="@{/book-edit(id=*{id})}">編集</a>
</div>
</div>
</div>
<a class="btn btn-primary mt-3" th:href="@{/book-create}">新規追加</a>
</div>
</body>
</html>
2023/02/19にBootstrapの記事を公開しました。その影響で少しhtmlの内容が変わっています。詳しくはこちらの記事をご確認ください。
edit.html
次に本の編集を行う画面である「edit.html」を作成します。
ポイントはhiddenタグでidを保有していることです。
idはデータベースから取得したものをhiddenタグを使って、画面で保持し、「更新」ボタンが押されたときにサーバーに送ります。
送られてきたidを元に、データベースの更新処理を行います。
<input type="hidden" th:field="*{id}" th:value="*{id}">
edit.htmlは次のようになります。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>本の情報を編集</title>
<link rel="stylesheet" th:href="@{/webjars/bootstrap/5.2.2/css/bootstrap.min.css}"/>
</head>
<body>
<div th:replace="share::header"></div>
<div class="container">
<h1>本の編集を行う</h1>
<form th:action="@{/book-edit}" th:object="${editBookForm}" method="POST">
<input type="hidden" th:field="*{id}" th:value="*{id}" />
<div class="mb-3">
<p th:if="${#fields.hasErrors('title')}" th:errors="*{title}" class="text-danger">Title Error</p>
<label for="bookTitle" class="form-label">タイトル</label>
<input id="bookTitle" class="form-control" type="text" th:field="*{title}">
</div>
<div class="mb-3">
<p th:if="${#fields.hasErrors('price')}" th:errors="*{price}" class="text-danger">Price Error</p>
<label for="bookPrice" class="form-label">値段</label>
<input id="bookPrice" class="form-control" type="number" th:field="*{price}">
</div>
<input type="submit" class="btn btn-primary" value="更新">
</form>
<a th:href="@{/book-list}" class="btn btn-secondary">一覧に戻る</a>
</div>
</body>
</html>
フォームの入力値を受け取る方法やバリデーションチェックを行う方法は次の記事も参考にしてみてください。
データ登録やバリデーションはこちら
EditBookForm.java
新規で編集機能ようのFormクラスを作成します。
こちらは、id, title, priceを保持するようにし、各フィールド毎にバリデーションの設定もしました。
package com.uhablog.form;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import lombok.Data;
@Data
public class EditBookForm {
/**
* 本のIDを保持する
* チェック内容:Nullでないこと
*/
@NotNull(message="IDがNullになっています")
private Integer id;
/**
* 本のタイトルを保持する
* チェック内容:未入力でないこと
*/
@NotBlank(message="タイトルを入力してください")
private String title;
/**
* 本の値段を保持する
* チェック内容:Nullでないこと、プラスであること
*/
@NotNull(message="値段を入力してください")
@Positive(message="値段はプラスの値を入力してください")
private Integer price;
}
BookController.java
次に「BookController.java」の編集を行います。
一覧画面でリンクが押されたときに編集画面を表示する「editBook」メソッドと、編集画面で入力された値で更新処理を実行する「update」メソッドを作成しました。
editBookメソッド
「editBook」メソッドではリクエストデータからidを取得して、serviceクラスのgetOneBookメソッドを呼び出して、編集対象のデータを取得しています。
取得したデータをmodelに設定して、編集画面を表示しています。
serviceクラスの処理については後ほど解説します。
// 編集画面を表示する
@GetMapping("/book-edit")
public String editBook(Model model, EditBookForm editBook) {
editBook = service.getOneBook(editBook.getId());
model.addAttribute(editBook);
return "edit";
}
・データベースからidを指定してデータを取得
・編集画面を表示
updateメソッド
「update」メソッドでは編集画面で編集された値を受け取って、更新処理を行います。
入力された値のバリデーションチェックを行い、エラーがあった場合は、編集画面をもう一度表示します。
入力値が正常だった場合は、serviceクラスのupdateメソッドを実行して、データの更新を行います。
その後、リダイレクトを使って、一覧画面を表示します。
// 本の情報を更新する
@PostMapping("/book-edit")
public String update(@ModelAttribute @Validated EditBookForm editBook, BindingResult result, Model model) {
// バリデーションエラーの場合
if (result.hasErrors()) {
// 編集画面に遷移
return "edit";
}
// 本を更新する
service.update(editBook);
// 本の一覧画面にリダイレクト
return "redirect:/book-list";
}
・バリデーションでエラーがあれば編集画面を再表示
・エラーがなければデータを更新して一覧画面を表示
Controller全体
コードが長いので、途中で省略していますが、Controllerの全体はおおむね次のようになります。
package com.uhablog.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import com.uhablog.form.BookForm;
import com.uhablog.form.EditBookForm;
import com.uhablog.model.Book;
import com.uhablog.service.BookService;
@Controller
public class BookController {
@Autowired
BookService service;
// 本の一覧画面を表示する
@GetMapping("/book-list")
public String bookList(Model model) {
// serviceを使って、本の一覧をDBから取得する
List<Book> bookList = service.findAll();
// modelに本の一覧を設定して、画面に渡す
model.addAttribute("bookList", bookList);
// bookList.htmlの表示
return "bookList";
}
・
・
・
// 編集画面を表示する
@GetMapping("/book-edit")
public String editBook(Model model, EditBookForm editBook) {
editBook = service.getOneBook(editBook.getId());
model.addAttribute(editBook);
return "edit";
}
// 本の情報を更新する
@PostMapping("/book-edit")
public String update(@ModelAttribute @Validated EditBookForm editBook, BindingResult result,Model model) {
// バリデーションエラーの場合
if (result.hasErrors()) {
// 編集画面に遷移
return "edit";
}
// 本を更新する
service.update(editBook);
// 本の一覧画面にリダイレクト
return "redirect:/book-list";
}
}
BookService.java
最後にServiceクラスを編集します。
Serviceクラスではidを受け取って、データを取得する「getOneBook」メソッドとデータの更新処理を行う「update」メソッドを実装します。
getOneBookメソッド
「getOneBook」メソッドではrepositoryのfindByIdメソッドを使って、データを取得します。
取得したデータを画面に表示するEditBookFormの形に整形して、返却します。
// 受け取ったidからデータを取得して、Formを返却する
public EditBookForm getOneBook(Integer id) {
// idを指定して本の情報を取得する
Book book = repository.findById(id).orElseThrow();
// 画面返却用のFormに値を設定する
EditBookForm editBook = new EditBookForm();
editBook.setId(book.getId());
editBook.setTitle(book.getTitle());
editBook.setPrice(book.getPrice());
return editBook;
}
・idを指定してデータを取得
・EditBookFormに変換して、データを返却
updateメソッド
「update」メソッドでは画面で入力された値を保持するEditBookFormを更新用にBookに変換して、repositoryのsaveメソッドを使って、更新処理を行います。
// 本を更新する
public void update(EditBookForm editBook) {
// データベースに登録する値を保持するインスタンスの作成
Book book = new Book();
// 画面から受け取った値を設定する
book.setId(editBook.getId());
book.setTitle(editBook.getTitle());
book.setPrice(editBook.getPrice());
// データベースを更新する
repository.save(book);
}
・入力られたデータBookに詰める
・データを更新する
Serviceの全体像
こちらも途中で省略していますが、全体像としては次のようになります。
package com.uhablog.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.uhablog.form.BookForm;
import com.uhablog.form.EditBookForm;
import com.uhablog.model.Book;
import com.uhablog.repository.BookRepository;
@Service
@Transactional
public class BookService {
@Autowired
BookRepository repository;
// データベースから本の一覧を取得する
public List<Book> findAll() {
return repository.findAll();
}
・
・
・
// 受け取ったidからデータを取得して、Formを返却する
public EditBookForm getOneBook(Integer id) {
// idを指定して本の情報を取得する
Book book = repository.findById(id).orElseThrow();
// 画面返却用のFormに値を設定する
EditBookForm editBook = new EditBookForm();
editBook.setId(book.getId());
editBook.setTitle(book.getTitle());
editBook.setPrice(book.getPrice());
return editBook;
}
// 本を更新する
public void update(EditBookForm editBook) {
// データベースに登録する値を保持するインスタンスの作成
Book book = new Book();
// 画面から受け取った値を設定する
book.setId(editBook.getId());
book.setTitle(editBook.getTitle());
book.setPrice(editBook.getPrice());
// データベースを更新する
repository.save(book);
}
}
動作確認
実際にサーバーを起動して動作確認をしてみましょう。
サーバーを起動して「http://localhost:8080/book-list」にアクセスすると一覧画面が表示され、編集ボタンが表示されています。
「編集」ボタンを押すと本の情報が表示された編集画面に遷移します。
タイトルを未入力、値段をマイナスの値にして「更新」ボタンを押すとエラーメッセージが表示されます。
正しい値を入力して、更新ボタンを押すと一覧画面が表示され、データが変わっていることがわかります。
今回の記事はここまでです。次はいよいよ最後、削除機能を実装します。
挫折せずにプログラミングを学ぶためには?
僕はプログラミングで挫折した経験があります。
エラーの連続やエラーが解消しても思った通りに動かないといったことが原因で、プログラミングが嫌いでした。
当時はパソコンの基礎すら分からず、Googleでの検索力もありませんでした。
「プログラミングって全然意味わからないし、全然楽しくない」そう思っていました。
そんな僕でも今はエンジニアとして働けています。
エンジニアとなった今、初心者の方は周りの人に聞ける環境というのがとても大切だと感じています。
周りに聞ける人がいない時は、学習環境を手に入れるためにお金を払うというのも一つの方法です。
それができるのが、プログラミングスクールのFreeksです。
Freeksは月額10,780円で現役エンジニアに質問する環境を手に入れることができるプログラミングスクールです。
多くのプログラミングスクールが数十万円払って通うところを月額10,780円から通うことができるのはコスパが良いです。
しかもサブスク制で、自分のペースで学ぶことができ嫌になったらすぐにやめることができます。
Freeksでは無料カウンセリングを行なっています。
「周りに誰も聞ける人がいなくて、エラーが解決できない」「プログラミング全然楽しくない」という方は、無料カウンセリングを受けてみて下さい。
【関連記事】Freeks評判、口コミ