8月6日

投稿者: | 2020年8月6日

アルバムに収録されている曲のリストを表示する。

コントローラで、AlbumのIDでMusicを検索し、結果をAlbumに渡す。

AlbumController.java

package jp.abc;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class AlbumController {
	@Autowired
	AlbumRepository repository;
	@Autowired
	MusicRepository musicRepository;

    @RequestMapping(value = "/album/{id}", method = RequestMethod.GET)
    public ModelAndView index(
    		@PathVariable long id,
    		ModelAndView mav) {
    	Optional<Album> data = repository.findById(id);
    	Album album = data.get();
    	List<Music> musics = musicRepository.findByAlbumId(id);
    	album.setMusics(musics);
    	mav.addObject("album", album);
        mav.addObject("template", "album");
        mav.addObject("fragment", "album");
        mav.setViewName("layout");
    	return mav;
    }
}

musicRepository.findByAlbumId()でコンパイルエラーが出るので、Eclipseのクイックフィックスでメソッドを生成する。

MusicRepository.java

package jp.abc;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

public interface MusicRepository extends JpaRepository<Music, Long> {
	public Optional<Music> findById(long id);

	public List<Music> findByAlbumId(long id);
}

出力されたHTMLを見ると、olタグがMusicの数だけ作られていた。
th:eachを記述する場所をliに移動する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Album</title>
</head>
<body>

<div th:fragment="album">
<h1>Album</h1>
<p>Albumフラグメント</p>
<p th:text="${msg}"></p>

<h2 th:text="${album.title}"></h2>
<h3 th:text="${album.artist}"></h3>
<p>収録曲</p>
<ol>
  <li th:each="music : ${album.musics}" th:text="${music.title}"></li>
</ol>

</div>

</body>
</html>

アルバムのジャケット画像も表示できるようにしたい。
まずテンプレートに画像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>画像URL</th>
		<td><input type="text" name="image" th:value="*{image}" /></td>
	</tr>
	<tr>
		<th></th>
		<td><input type="submit" value="登録" /></td>
	</tr>
</table>

</form>
(以下略)

Albumエンティティに画像URLのメンバーを追加する。

package jp.abc;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Album {
	@Id
    @Column
    @GeneratedValue
	private long id;

	@Column(length = 100, nullable = false)
	private String title;

	@Column(length = 100, nullable = false)
	private String artist;

	@Column
	private String image;

	@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	private List<Music> musics;

	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 String getImage() {
		return image;
	}
	public void setImage(String image) {
		this.image = image;
	}
	public List<Music> getMusics() {
		return musics;
	}
	public void setMusics(List<Music> musics) {
		this.musics = musics;
	}
}

albumテンプレートに画像を表示するためのタグを追加する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Album</title>
</head>
<body>

<div th:fragment="album">
<h1>Album</h1>
<p>Albumフラグメント</p>
<p th:text="${msg}"></p>

<h2 th:text="${album.title}"></h2>
<h3 th:text="${album.artist}"></h3>
<img th:src="${album.image}" width="200px" />
<p>収録曲</p>
<ol>
  <li th:each="music : ${album.musics}" th:text="${music.title}"></li>
</ol>

</div>

</body>
</html>

musicplayerテンプレートのeditフラグメントにも画像URLの入力フィールドを追加する。

<div th:fragment="edit">

<form action="/edit" method="post" th:object="${album}">
<input type="hidden" name="id" th:value="*{id}" />
<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>画像URL</th>
		<td><input type="text" name="image" th:value="*{image}" /></td>
	</tr>
	<tr>
		<th></th>
		<td><input type="submit" value="登録" /></td>
	</tr>
</table>

</form>

</div>

トップページのアルバムのリスト表示しているところでも、画像を小さく表示してみる。

<table>
  <tr>
    <th>ID</th>
    <th>タイトル</th>
    <th>アーティスト</th>
    <th>操作</th>
  </tr>
  <tr th:each="album : ${list}">
    <td th:text="${album.id}"></td>
    <td>
      <img th:src="${album.image}" width="30px" />
      <a th:href="@{'/album/' + ${album.id}}" th:text="${album.title}"></a>
    </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>

アルバムのページから曲を登録できるようにする。
album.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Album</title>
</head>
<body>

<div th:fragment="album">
<h1>Album</h1>
<p>Albumフラグメント</p>
<p th:text="${msg}"></p>

<h2 th:text="${album.title}"></h2>
<h3 th:text="${album.artist}"></h3>
<img th:src="${album.image}" width="200px" />
<p>収録曲</p>
<ol>
  <li th:each="music : ${album.musics}" th:text="${music.title}"></li>
</ol>

<form action="/music" method="post" th:object="${music}">

<table>
  <tr>
    <th>タイトル</th>
    <td>
      <input type="text" name="title" th:value="*{title}" />
      <div th:if="${#fields.hasErrors('title')}" th:errors="*{title}"></div>
    </td>
  </tr>
  <tr>
    <th>Albumのid</th>
    <td>
      <span th:text="${album.id}"></span>
      <input type="hidden" name="album" th:value="${album.id}" />
    </td>
  </tr>
  <tr>
    <th></th><td><input type="submit" value="登録" /></td>
  </tr>
</table>

</form>

</div>

</body>
</html>

AlbumController.java

    @RequestMapping(value = "/album/{id}", method = RequestMethod.GET)
    public ModelAndView index(
    		@PathVariable long id,
    		ModelAndView mav) {
    	Optional<Album> data = repository.findById(id);
    	Album album = data.get();
    	List<Music> musics = musicRepository.findByAlbumId(id);
    	album.setMusics(musics);
    	mav.addObject("album", album);
    	mav.addObject("music", new Music());
        mav.addObject("template", "album");
        mav.addObject("fragment", "album");
        mav.setViewName("layout");
    	return mav;
    }