MyDataを編集(CRUDのUpadate)するための機能を追加する。
テンプレートに編集用のフラグメントを追加する。
<div th:fragment="edit">
<form action="/edit" method="post" th:object="${mydata}">
<table>
<tr>
<td>名前</td>
<td><input type="text" name="name" th:value="*{name}" /></td>
</tr>
<tr>
<td>年齢</td>
<td><input type="text" name="age" th:value="*{age}" /></td>
</tr>
<tr>
<td>メール</td>
<td><input type="text" name="mail" th:value="*{mail}" /></td>
</tr>
<tr>
<td>メモ</td>
<td><textarea rows="5" cols="20" name="memo" th:text="*{memo}"></textarea></td>
</tr>
<tr>
<td></td><td><input type="submit" value="送信" /></td>
</tr>
</table>
</form>
</div>
MyDataRepository に findById() を追加する。
package jp.abc;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MyDataRepository extends JpaRepository<MyData, Long> {
public Optional<MyData> findById(long id);
}
コントローラで MyData を取得してテンプレートに渡す。
@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public ModelAndView edit(
@ModelAttribute("mydata") MyData mydata,
@PathVariable long id,
ModelAndView mav) {
Optional<MyData> data = myDataRepository.findById(id);
MyData myData = data.get();
mav.addObject("mydata", myData);
mav.addObject("template", "mydata");
mav.addObject("fragment", "edit");
mav.setViewName("layout");
return mav;
}
POSTメソッドを受け取れるようにコントローラを修正する。
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public ModelAndView update(
@ModelAttribute("mydata") MyData mydata,
ModelAndView mav) {
return new ModelAndView("redirect:/");
}
テンプレートに id のデータを持つための input を追加する。
<div th:fragment="edit">
<form action="/edit" method="post" th:object="${mydata}">
<input type="hidden" name="id" th:value="*{id}" />
<table>
<tr>
<td>名前</td>
<td><input type="text" name="name" th:value="*{name}" /></td>
</tr>
コントローラにデータベースを更新する処理を追加する。
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public ModelAndView update(
@ModelAttribute("mydata") MyData mydata,
ModelAndView mav) {
myDataRepository.saveAndFlush(mydata);
return new ModelAndView("redirect:/");
}
CRUD のうち、Create/Read/Update ができたので、次は Delete を実装する。
まずは、削除するためのリンクを用意する。
<table>
<tr>
<th>ID</th>
<th>名前</th>
<th>メール</th>
<th>年齢</th>
<th>操作</th>
</tr>
<tr th:each="mydata : ${list}">
<td th:text="${mydata.id}"></td>
<td th:text="${mydata.name}"></td>
<td th:text="${mydata.mail}"></td>
<td th:text="${mydata.age}"></td>
<td>
<a th:href="@{'/edit/' + ${mydata.id}}">編集</a>
<a th:href="@{'/delete/' + ${mydata.id}}">削除</a>
</td>
</tr>
</table>
サーバー側で用意してないので、削除をクリックすると404エラーになる。
コントローラを修正して、/delete/{id} を受け付けるようにする。
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public ModelAndView delete(
@ModelAttribute("mydata") MyData mydata,
@PathVariable long id,
ModelAndView mav) {
Optional<MyData> data = myDataRepository.findById(id);
MyData myData = data.get();
mav.addObject("mydata", myData);
mav.addObject("template", "mydata");
mav.addObject("fragment", "delete");
mav.setViewName("layout");
return mav;
}
delete用のフラグメントを用意する。
mydata.html に以下の2行を追加する。
<div th:fragment="delete"> </div>
フラグメント内に削除するデータの内容を表示する。
<div th:fragment="delete">
<p>このデータを削除しますか?</p>
<form action="/delete" method="post" th:object="${mydata}">
<input type="hidden" name="id" th:value="*{id}" />
<table>
<tr>
<td>名前</td>
<td th:text="*{name}"></td>
</tr>
<tr>
<td>年齢</td>
<td th:text="*{age}"></td>
</tr>
<tr>
<td>メール</td>
<td th:text="*{mail}"></td>
</tr>
<tr>
<td>メモ</td>
<td><textarea rows="5" cols="20" name="memo" th:text="*{memo}" readonly></textarea></td>
</tr>
<tr>
<td></td><td><input type="submit" value="削除" /></td>
</tr>
</table>
</form>
</div>
コントローラに /delete に対する POST メソッドを受け付けるメソッドを追加する。
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public ModelAndView remove(
@RequestParam long id,
ModelAndView mav) {
myDataRepository.deleteById(id);
return new ModelAndView("redirect:/");
}
現状は、名前などが空欄だったり、不正なメールアドレスでも登録できてしまうので、あまりよろしくない。
入力チェックを追加する。
そのための仕組みがバリデーションと呼ばれている。
まずバリデーションを行うためのライブラリを追加する。
pom.xml に以下の内容を追加する。
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.5.Final</version> </dependency>
MyData にバリデーションのためのアノテーションを追加する。
package jp.abc;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.Email;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import com.sun.istack.NotNull;
@Entity // my_dataテーブルと関連付けられる
public class MyData {
@Id
@Column
@GeneratedValue
@NotNull
private long id;
@Column(length = 100, nullable = false)
@NotEmpty
private String name;
@Column(length = 100, nullable = false)
@Email
private String mail;
@Column
@Min(0)
private int age;
@Column(nullable = true)
private String memo;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
}
コントローラにバリデーションに対応するためのコードを追加する。
@RequestMapping(value = "/", method = RequestMethod.POST)
public ModelAndView post(
@ModelAttribute("mydata") @Validated MyData mydata,
BindingResult result,
ModelAndView mav) {
if (result.hasErrors()) {
List<MyData> list = myDataRepository.findAll();
mav.addObject("list", list);
mav.addObject("template", "mydata");
mav.addObject("fragment", "mydata");
mav.setViewName("layout");
mav.addObject("msg", "validation error");
return mav;
}
myDataRepository.saveAndFlush(mydata);
return new ModelAndView("redirect:/");
}
テンプレートにメッセージを表示する要素を追加する。
<div th:fragment="mydata">
<h1>MyData</h1>
<p>MyDataフラグメント</p>
<p th:text="${msg}"></p>
<form action="/" method="post" th:object="${mydata}">
<table>
エラーメッセージを表示する。
<div th:fragment="mydata">
<h1>MyData</h1>
<p>MyDataフラグメント</p>
<p th:text="${msg}"></p>
<form action="/" method="post" th:object="${mydata}">
<ul>
<li th:each="error : ${#fields.detailedErrors()}" th:text="${error.message}"></li>
</ul>
<table>