MusicPlayerのCRUDを作っていく。
Create部分を作成する。
musicplayerテンプレートに、登録用のフォームを作成する。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>MusicPlayer</title>
</head>
<body>
<div th:fragment="musicplayer">
<h1>MusicPlayer</h1>
<p>MusicPlayerフラグメント</p>
<p th:text="${msg}"></p>
<form action="/" method="post" th:object="${album}">
<table>
<tr>
<th>タイトル</th>
<td><input type="text" name="title" th:value="*{title}" /></td>
</tr>
<tr>
<th>アーティスト</th>
<td><input type="text" name="artist" th:value="*{artist}" /></td>
</tr>
<tr>
<th></th>
<td><input type="submit" value="登録" /></td>
</tr>
</table>
</form>
<table>
<tr><th>ID</th><th>タイトル</th><th>アーティスト</th></tr>
<tr th:each="album : ${list}">
<td th:text="${album.id}"></td>
<td th:text="${album.title}"></td>
<td th:text="${album.artist}"></td>
</tr>
</table>
</div>
</body>
</html>
再起動してアクセスすると500エラーが発生した。
musicplayerテンプレートの19行目でエラー。
titleを参照しようとしたが、th:objectで指定した名前に対応する値が存在しないためにエラーになっている。
コントローラでalbumを作ってModelAndViewに渡す。
package jp.abc;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class IndexController {
@Autowired
AlbumRepository repository;
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
List<Album> list = repository.findAll();
Album album = new Album();
mav.addObject("album", album);
mav.addObject("list", list);
mav.addObject("template", "musicplayer");
mav.addObject("fragment", "musicplayer");
mav.setViewName("layout");
return mav;
}
}
コントローラでGETとPOSTを別々のメソッドで受け取るようにする。
package jp.abc;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class IndexController {
@Autowired
AlbumRepository repository;
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(
@ModelAttribute("album") Album album,
ModelAndView mav) {
List<Album> list = repository.findAll();
mav.addObject("album", album);
mav.addObject("list", list);
mav.addObject("template", "musicplayer");
mav.addObject("fragment", "musicplayer");
mav.setViewName("layout");
return mav;
}
@RequestMapping(value = "/", method = RequestMethod.POST)
public ModelAndView post(
@ModelAttribute("album") Album album,
ModelAndView mav) {
repository.saveAndFlush(album);
return new ModelAndView("redirect:/");
}
}
CRUC の Update 機能を追加する。
HTMLテンプレートに編集用のリンクを追加する。
編集用のフラグメントを追加する。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>MusicPlayer</title>
</head>
<body>
<div th:fragment="musicplayer">
<h1>MusicPlayer</h1>
<p>MusicPlayerフラグメント</p>
<p th:text="${msg}"></p>
<form action="/" method="post" th:object="${album}">
<table>
<tr>
<th>タイトル</th>
<td><input type="text" name="title" th:value="*{title}" /></td>
</tr>
<tr>
<th>アーティスト</th>
<td><input type="text" name="artist" th:value="*{artist}" /></td>
</tr>
<tr>
<th></th>
<td><input type="submit" value="登録" /></td>
</tr>
</table>
</form>
<table>
<tr>
<th>ID</th>
<th>タイトル</th>
<th>アーティスト</th>
<th>操作</th>
</tr>
<tr th:each="album : ${list}">
<td th:text="${album.id}"></td>
<td th:text="${album.title}"></td>
<td th:text="${album.artist}"></td>
<td><a th:href="@{'/edit/' + ${album.id}}">編集</a></td>
</tr>
</table>
</div>
<div th:fragment="edit">
</div>
</body>
</html>
編集用の edit フラグメントの中身は、登録用のformをコピーして、action のURLだけを変更する。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>MusicPlayer</title>
</head>
<body>
<div th:fragment="musicplayer">
<h1>MusicPlayer</h1>
<p>MusicPlayerフラグメント</p>
<p th:text="${msg}"></p>
<form action="/" method="post" th:object="${album}">
<table>
<tr>
<th>タイトル</th>
<td><input type="text" name="title" th:value="*{title}" /></td>
</tr>
<tr>
<th>アーティスト</th>
<td><input type="text" name="artist" th:value="*{artist}" /></td>
</tr>
<tr>
<th></th>
<td><input type="submit" value="登録" /></td>
</tr>
</table>
</form>
<table>
<tr>
<th>ID</th>
<th>タイトル</th>
<th>アーティスト</th>
<th>操作</th>
</tr>
<tr th:each="album : ${list}">
<td th:text="${album.id}"></td>
<td th:text="${album.title}"></td>
<td th:text="${album.artist}"></td>
<td><a th:href="@{'/edit/' + ${album.id}}">編集</a></td>
</tr>
</table>
</div>
<div th:fragment="edit">
<form action="/edit" method="post" th:object="${album}">
<table>
<tr>
<th>タイトル</th>
<td><input type="text" name="title" th:value="*{title}" /></td>
</tr>
<tr>
<th>アーティスト</th>
<td><input type="text" name="artist" th:value="*{artist}" /></td>
</tr>
<tr>
<th></th>
<td><input type="submit" value="登録" /></td>
</tr>
</table>
</form>
</div>
</body>
</html>
AlbumRepository に findById() を追加する。
package jp.abc;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AlbumRepository extends JpaRepository<Album, Long> {
public Optional<Album> findById(long id);
}
コントローラで /edit を受け付けるようにする。
@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public ModelAndView edit(
@ModelAttribute("album") Album album,
@PathVariable long id,
ModelAndView mav) {
Optional<Album> data = repository.findById(id);
album = data.get();
mav.addObject("album", album);
mav.addObject("template", "musicplayer");
mav.addObject("fragment", "edit");
mav.setViewName("layout");
return mav;
}
入力フォームにはIDがないので、どのデータを更新していいのかわからない。
hiddenでidを追加する。
<div th:fragment="edit">
<form action="/edit" method="post" th:object="${album}">
<input type="hidden" name="id" th:value="*{id}" />
<table>
コントローラでPOSTメソッドを受け付けるようにする。
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public ModelAndView update(
@ModelAttribute("album") Album album,
ModelAndView mav) {
repository.saveAndFlush(album);
return new ModelAndView("redirect:/");
}
CRUD のうち、Create/Read/Update ができたので、次は Delete を実装する。
削除するためのリンクを用意する。
musicplayer.html
<table>
<tr>
<th>ID</th>
<th>タイトル</th>
<th>アーティスト</th>
<th>操作</th>
</tr>
<tr th:each="album : ${list}">
<td th:text="${album.id}"></td>
<td th:text="${album.title}"></td>
<td th:text="${album.artist}"></td>
<td>
<a th:href="@{'/edit/' + ${album.id}}">編集</a>
<a th:href="@{'/delete/' + ${album.id}}">削除</a>
</td>
</tr>
</table>
コントローラに /delete へのリクエストを受け取るためのメソッドを用意する。
edit() とほぼ同じなので、コピーしてurlとメソッド名を変更する。
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public ModelAndView delete(
@ModelAttribute("album") Album album,
@PathVariable long id,
ModelAndView mav) {
Optional<Album> data = repository.findById(id);
album = data.get();
mav.addObject("album", album);
mav.addObject("template", "musicplayer");
mav.addObject("fragment", "edit");
mav.setViewName("layout");
return mav;
}
フラグメントはeditのままなので、このまま動作させると、削除のリンクをクリックすると、編集用の画面が表示される。
削除用のフラグメントを追加する。
musicplayer.html
<div th:fragment="delete">
<p>このデータを削除しますか?</p>
<form action="/delete" method="post" th:object="${album}">
<input type="hidden" name="id" th:value="*{id}" />
<table>
<tr>
<td>タイトル</td>
<td th:text="*{title}"></td>
</tr>
<tr>
<td>アーティスト</td>
<td th:text="*{artist}"></td>
</tr>
<tr>
<td></td><td><input type="submit" value="削除" /></td>
</tr>
</table>
</form>
</div>
削除用のフラグメントを追加したので、コントローラで削除用のフラグメントを使うように修正する。
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public ModelAndView delete(
@ModelAttribute("album") Album album,
@PathVariable long id,
ModelAndView mav) {
Optional<Album> data = repository.findById(id);
album = data.get();
mav.addObject("album", album);
mav.addObject("template", "musicplayer");
mav.addObject("fragment", "delete");
mav.setViewName("layout");
return mav;
}
コントローラに削除のPOSTメソッドを受け取るためのメソッドを追加する。
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public ModelAndView remove(
@RequestParam long id,
ModelAndView mav) {
repository.deleteById(id);
return new ModelAndView("redirect:/");
}