個別のプレイリストの画面を表示できるようにする。
まず、プレイリストの一覧をテーブルで表示しているところの、プレイリスト名をリンクに変更する。
<h3>プレイリスト</h3>
<table>
<tr>
<th>ID</th>
<th>名前</th>
</tr>
<tr th:each="playlist : ${playlists}">
<td th:text="${playlist.id}"></td>
<td><a th:href="@{'/playlist/' + ${playlist.id}}" th:text="${playlist.name}"></a></td>
</tr>
</table>
IndexController で、URL /playlist/{id} を受け付けるようにする。
@RequestMapping(value="/playlist/{id}", method=RequestMethod.GET)
public ModelAndView playlist(ModelAndView mav,
@PathVariable long id) {
Optional<PlayList> r = playListRepository.findById(id);
PlayList pl = r.get();
mav.addObject("playlist", pl);
mav.setViewName("playlist");
return mav;
}
Optionalをインポートするときは、java.util の Optional をインポートする。
これで、プレイリスト名がリンクで表示できるようになる。
プレイリスト名のリンクをクリックすると、まだテンプレートを作ってないのでエラーになる。
/playlist で表示するためのテンプレートを用意する。
src/main/resources の templates に playlist.html を作成する。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>プレイリスト</title>
</head>
<body>
<h1 th:text="${playlist.name}"></h1>
</body>
</html>
プレイリストに音楽を追加できるようにする。
とりあえず、音楽のリストを index.html からコピーしてきて、削除のリンクを追加に変更する。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>プレイリスト</title>
</head>
<body>
<h1 th:text="${playlist.name}"></h1>
<h3>このプレイリストに音楽を追加する</h3>
<h3>Musicリスト</h3>
<table>
<tr>
<th>ID</th>
<th>タイトル</th>
<th>アーティスト</th>
<th>操作</th>
</tr>
<tr th:each="music : ${musics}">
<td th:text="${music.id}"></td>
<td th:text="${music.title}"></td>
<td th:text="${music.artist}"></td>
<td><a th:href="@{'/addtoplaylist/' + ${playlist.id} + '/' + ${music.id}}">追加</a></td>
</tr>
</table>
</body>
</html>
IndexController で musics を playlist テンプレートに渡すようにする。
@RequestMapping(value="/playlist/{id}", method=RequestMethod.GET)
public ModelAndView playlist(ModelAndView mav,
@PathVariable long id) {
Optional<PlayList> r = playListRepository.findById(id);
PlayList pl = r.get();
mav.addObject("playlist", pl);
List<Music> musics = musicRepository.findAll();
mav.addObject("musics", musics);
mav.setViewName("playlist");
return mav;
}
/addtoplaylist/{pid}/{mid} では、id=pid のプレイリストに id=mid の音楽を追加したい。
なので、以下のようにコードを書いてみる。
@RequestMapping(value="/addtoplaylist/{pid}/{mid}", method=RequestMethod.GET)
public ModelAndView addToPlaylist(ModelAndView mav,
@PathVariable long pid,
@PathVariable long mid) {
Optional<PlayList> pr = playListRepository.findById(pid);
PlayList pl = pr.get();
Optional<Music> mr = musicRepository.findById(mid);
Music m = mr.get();
pl.addMusic(m);
playListRepository.saveAndFlush(pl);
return mav;
}
pl.addMusic(m) のところでコンパイルエラーになっているので、クイックフィックスでメソッドを作成してエラーを消す。
package jp.kpc;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Entity
public class PlayList {
@Id
@GeneratedValue
@Column
@NotNull
private long id;
@Column
@NotEmpty
private String name;
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 void addMusic(Music m) {
}
}
プレイリストを追加する addToPlaylist() では、/playlist/{pid} にリダイレクトする。
@RequestMapping(value="/addtoplaylist/{pid}/{mid}", method=RequestMethod.GET)
public ModelAndView addToPlaylist(ModelAndView mav,
@PathVariable long pid,
@PathVariable long mid) {
Optional<PlayList> pr = playListRepository.findById(pid);
PlayList pl = pr.get();
Optional<Music> mr = musicRepository.findById(mid);
Music m = mr.get();
pl.addMusic(m);
playListRepository.saveAndFlush(pl);
return new ModelAndView("redirect:/playlist/" + pid);
}
ひとつの PlayList に対して複数の Music を関連付ける。
PlayList
package jp.kpc;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Entity
public class PlayList {
@Id
@GeneratedValue
@Column
@NotNull
private long id;
@Column
@NotEmpty
private String name;
@OneToMany
private List<Music> musics;
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 void addMusic(Music m) {
musics.add(m);
}
public List<Music> getMusics() {
return musics;
}
public void setMusics(List<Music> musics) {
this.musics = musics;
}
}
Music
package jp.kpc;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Entity
public class Music {
@Id
@GeneratedValue
@Column
@NotNull
private long id;
@Column
@NotEmpty
private String title;
@Column
@NotEmpty
private String artist;
@ManyToOne
private PlayList playList;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public PlayList getPlayList() {
return playList;
}
public void setPlayList(PlayList playList) {
this.playList = playList;
}
}
テンプレート playlist に、プレイリストに登録済みの音楽リストを追加する。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>プレイリスト</title>
</head>
<body>
<h1 th:text="${playlist.name}"></h1>
<h3>このプレイリストに追加されている音楽</h3>
<table>
<tr>
<th>ID</th>
<th>タイトル</th>
<th>アーティスト</th>
</tr>
<tr th:each="music : ${playlist.musics}">
<td th:text="${music.id}"></td>
<td th:text="${music.title}"></td>
<td th:text="${music.artist}"></td>
</tr>
</table>
<h3>このプレイリストに音楽を追加する</h3>
<h3>Musicリスト</h3>
<table>
<tr>
<th>ID</th>
<th>タイトル</th>
<th>アーティスト</th>
<th>操作</th>
</tr>
<tr th:each="music : ${musics}">
<td th:text="${music.id}"></td>
<td th:text="${music.title}"></td>
<td th:text="${music.artist}"></td>
<td><a th:href="@{'/addtoplaylist/' + ${playlist.id} + '/' + ${music.id}}">追加</a></td>
</tr>
</table>
</body>
</html>
プレイリストから音楽を削除するためのリンクを追加する。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>プレイリスト</title>
</head>
<body>
<h1 th:text="${playlist.name}"></h1>
<h3>このプレイリストに追加されている音楽</h3>
<table>
<tr>
<th>ID</th>
<th>タイトル</th>
<th>アーティスト</th>
<th>操作</th>
</tr>
<tr th:each="music : ${playlist.musics}">
<td th:text="${music.id}"></td>
<td th:text="${music.title}"></td>
<td th:text="${music.artist}"></td>
<td><a th:href="@{'/delete-music-from-playlist/' + ${playlist.id} + '/' + ${music.id}}">削除</a></td>
</tr>
</table>
<h3>このプレイリストに音楽を追加する</h3>
<h3>Musicリスト</h3>
<table>
<tr>
<th>ID</th>
<th>タイトル</th>
<th>アーティスト</th>
<th>操作</th>
</tr>
<tr th:each="music : ${musics}">
<td th:text="${music.id}"></td>
<td th:text="${music.title}"></td>
<td th:text="${music.artist}"></td>
<td><a th:href="@{'/addtoplaylist/' + ${playlist.id} + '/' + ${music.id}}">追加</a></td>
</tr>
</table>
</body>
</html>
削除のリンクをクリックすると、Not Found のエラーになる。
コントローラでURLに対応したマッピングを作成する。
@RequestMapping(value="/delete-music-from-playlist/{pid}/{mid}", method=RequestMethod.GET)
public ModelAndView deleteFromPlaylist(ModelAndView mav,
@PathVariable long pid,
@PathVariable long mid) {
Optional<PlayList> pr = playListRepository.findById(pid);
PlayList pl = pr.get();
Optional<Music> mr = musicRepository.findById(mid);
Music m = mr.get();
pl.deleteMusic(m);
playListRepository.saveAndFlush(pl);
return new ModelAndView("redirect:/playlist/" + pid);
}
94行目のdeleteMusic()でコンパイルエラーが出ているので、クイックフィックスでメソッドを作成する。
PlayList
package jp.kpc;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Entity
public class PlayList {
@Id
@GeneratedValue
@Column
@NotNull
private long id;
@Column
@NotEmpty
private String name;
@OneToMany
private List<Music> musics;
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 void addMusic(Music m) {
musics.add(m);
}
public void deleteMusic(Music m) {
musics.remove(m);
}
public List<Music> getMusics() {
return musics;
}
public void setMusics(List<Music> musics) {
this.musics = musics;
}
}
プレイリストの名前を変更できるようにする
playlist.html に入力フォームを追加する。
<h3>プレイリストの名前を変更する</h3>
<form action="/rename" method="post">
<input type="hidden" name="id" th:value="${playlist.id}" />
<input type="text" name="name" />
<input type="submit" value="変更" />
</form>
コントローラに、名前を変更するためのマッピングを作成する。
@RequestMapping(value="/rename", method=RequestMethod.POST)
public ModelAndView rename(ModelAndView mav,
@RequestParam("id") long id,
@RequestParam("name") String name) {
Optional<PlayList> r = playListRepository.findById(id);
PlayList pl = r.get();
pl.setName(name);
playListRepository.saveAndFlush(pl);
return new ModelAndView("redirect:/playlist/" + id);
}