前期提出課題

プロジェクト

プロジェクト名: se3NN (NN は学籍番号の下2桁)
パッケージ名: jp.abc

MyBootApp と同様のWebアプリケーションを作成する。
MyDataのかわりに、Userクラスを作成し、MsgDataクラスの代わりに Tweetクラスを作成する。

作成するページとURL

トップページ: http://localhost:8080/
ユーザー一覧&ユーザー登録: http://localhost:8080/user/
ユーザー編集ページ: http://localhost:8080/edit/{id}
ツイート一覧&ツイート投稿: http://localhost:8080/tweet/

エンティティ

User
・id – Long
・name – String
・profile – String
・tweets – List<Tweet>
Tweet
・id – Long
・time – java.util.Date
・content – String
・user – User

作成するHTMLテンプレート

  • index.html : トップページ
  • user.html : ユーザー一覧&ユーザー登録ページ
  • edit.html : ユーザー編集ページ
  • tweet.html : ツイート一覧&ツイート投稿ページ

トップページの内容

  • titleとh1タグに番号と名前を書くこと
  • ユーザー一覧&ユーザー登録ページへのリンクを作成
  • ツイート一覧&ツイート投稿ページへのリンクを作成

ユーザー一覧&ユーザー登録ページの内容

  • titleとh1タグに番号と名前を書くこと
  • h1のすぐ下にトップページへのリンクを作成
  • 入力フォームで名前(name)と自己紹介(profile)を入力できる
  • 自己紹介はtextareaにすること
  • 名前は1文字以上30文字以下
  • 自己紹介は1文字以上200文字以下
  • 送信ボタンを表示
  • 入力フォームの下に、登録済みユーザー一覧を表示する
  • ユーザー一覧にはID、名前、編集ページへのリンクを表示する

ユーザー編集ページの内容

  • titleとh1タグに番号と名前を書くこと
  • h1のすぐ下にトップページへのリンクを作成
  • 入力フォームに編集前の名前と自己紹介を表示
  • 入力フォームで名前と自己紹介を入力できる
  • 送信ボタンを表示

ツイート一覧&投稿ページの内容

  • titleとh1タグに番号と名前を書くこと
  • h1のすぐ下にトップページへのリンクを作成
  • 入力フォームで投稿内容(content)を入力できる
  • 投稿は1文字以上140文字以下
  • 投稿欄はtextareaにすること
  • 送信ボタンを表示
  • 日時はフォームに用意せず、コントローラが現在時刻を設定する
  • 入力フォームの下に、投稿済みツイート一覧を表示する
  • 投稿一覧にはID、名前、日時、投稿内容を表示する

application.properties

spring.datasource.url=jdbc:hsqldb:hsql://localhost/se3NN  ←NNは学籍番号の下2桁
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.jpa.hibernate.ddl-auto=update

hsqldb.bat
データベースインスタンスを追加する。
インスタンス名は se3NN (NNは学籍番号の下2桁)

cd (hsqldbの置き場所)\lib
java -cp hsqldb.jar org.hsqldb.Server --database.0 db/mydata --dbname.0 mydata --database.1 db/se3NN --dbname.1 se3NN

課題提出方法

プロジェクトを作成したフォルダを、エクスプローラで開く。

フォルダ「se3NN」(NNは学籍番号の下2桁)を右クリックし、[送る]-[圧縮(zip 形式)フォルダー]を選択する。
se3NN.zip ファイルができるので、そのファイルを提出する。

提出先

サーバーの以下のフォルダに提出。

\\stfs\ABKC\課題提出用\澤田\2019_SE3\課題提出

配点

接続先データベースや、プロジェクト名、番号・名前の間違いは、他人のものをコピーしたと判断し0点。
コピペもOKだけど最低限ができてなければ論外。
Webサイトを作って納品してもサイト名や会社名が間違ってたら、まず次の仕事はない。

  1. トップページ : 10点
    • titleとh1に番号と名前
    • ユーザーページへのリンク
    • 投稿ページへのリンク
  2. ユーザー一覧&ユーザー登録(GET) : 10点
    • titleとh1に番号と名前
    • 入力フォーム
    • 送信ボタン
    • ユーザー一覧
    • トップページへのリンク
  3. ユーザー一覧&ユーザー登録(POST) : 10点
    • 名前のエラーチェック
    • 自己紹介のエラーチェック
    • エラーメッセージ
    • データベースに保存
  4. ユーザー編集(GET) : 10点
    • titleとh1に番号と名前
    • 入力フォーム
    • 送信ボタン
    • トップページへのリンク
  5. ユーザー編集(POST) : 10点
    • 名前のエラーチェック
    • 自己紹介のエラーチェック
    • エラーメッセージ
    • データベースに保存
  6. ツイート一覧&投稿(GET) : 10点
    • titleとh1に番号と名前
    • 入力フォーム
    • 送信ボタン
    • ツイート一覧
    • トップページへのリンク
  7. ツイート一覧&投稿(POST) : 10点
    • 投稿内容のエラーチェック
    • 現在時刻を自動設定
    • エラーメッセージ
    • データベースに保存
  8. ツイート一覧で投稿者名が表示される(エンティティの連携) : 10点
  9. エラーメッセージの日本語化(全部できていれば) : 10点
  10. ツイート投稿でSELECT/OPTIONでユーザーを選択できる : 10点
  11. ツイート一覧でIDと名前の下に投稿が表示される : 10点
  12. ツイート一覧で複数行投稿がきちんと表示される : 10点
  13. トップページに授業の感想・意見を書く : 1〜20点

※1〜8はプログラムで採点しています。なので、1〜8の部分点はありません。
※14の授業の感想・意見は参考になった度合いで加点します。
※配点の総合計は100点を超えてますが、最大は100点です。

提出期限

7月19日(金)17:00

7月5日

プレイリストを登録できるようにする

リポジトリを作成する。

PlayListRepository.java

package jp.abc;

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

public interface PlayListRepository extends JpaRepository<PlayList, Long> {

}

コントローラが、GETとPOSTメソッドを受け取るように修正する。

package jp.abc;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.annotation.Validated;
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 PlayListController {

	@Autowired
	private PlayListRepository repository;

	@RequestMapping(value = "/playlist", method = RequestMethod.GET)
	public ModelAndView list(ModelAndView mav) {
		mav.setViewName("playlist");
		PlayList pl = new PlayList();
		mav.addObject("formModel", pl);
		List<PlayList> list = repository.findAll();
		mav.addObject("datalist", list);
		return mav;
	}

	@RequestMapping(value = "playlist", method = RequestMethod.POST)
	public ModelAndView post(
			@ModelAttribute("formModel") @Validated PlayList playlist,
			Errors result,
			ModelAndView mav) {
		if (result.hasErrors()) {
			mav.addObject("msg", "エラーですよ");
			return mav;
		}
		repository.saveAndFlush(playlist);
		return new ModelAndView("redirect:/playlist");
	}
}

HTMLテンプレートを修正する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>プレイリスト</title>
<style type="text/css">
h1 {
  font-size: 18pt;
  font-weight: bold;
  color: gray;
}
body {
  font-size: 13pt;
  color: gray;
  margin: 5px 25px;
}
pre {
  border: solid 3px #ddd;
  padding: 10px;
}
tr {
  margin: 5px;
}
th {
  padding: 5px;
  color: white;
  background: darkgray;
}
td {
  padding: 5px;
  color: black;
  background: #f0f0f0;
}
.err {
  color: red;
}
</style>
</head>
<body>

<h1>プレイリスト</h1>
<p th:text="${msg}"></p>
<form method="post" action="/playlist" th:object="${formModel}">
  <table>
    <tr>
      <td><label for="name">名前</label></td>
      <td>
        <input type="text" name="name" th:value="*{name}"
      			th:errorclass="err" />
      	<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" /></td>
    </tr>
  </table>
</form>

<hr />
<table>
  <tr>
    <th>ID</th><th>名前</th>
  </tr>
  <tr th:each="obj : ${datalist}">
    <td th:text="${obj.id}"></td>
    <td th:text="${obj.name}"></td>
  </tr>
</table>

</body>
</html>

PlayListとMusicを連携する

MusicからPlayListへの関連性を追加する。

package jp.abc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class Music {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	private long id;

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

	@Column(length = 200, nullable = false)
	@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;
	}

	@Override
	public String toString() {
		return "Music [title=" + title + ", artist=" + artist + "]";
	}

	public PlayList getPlaylist() {
		return playlist;
	}

	public void setPlaylist(PlayList playlist) {
		this.playlist = playlist;
	}

}

PlayListからMusicへの関連性を追加する。

package jp.abc;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class PlayList {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	private long id;

	@Column(length = 200, nullable = false)
	@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 List<Music> getMusics() {
		return musics;
	}

	public void setMusics(List<Music> musics) {
		this.musics = musics;
	}


}

Music を登録するHTMLテンプレート index.html に、プレイリストを設定するフィールドを追加する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ミュージックプレイヤー</title>
<style type="text/css">
h1 {
  font-size: 18pt;
  font-weight: bold;
  color: gray;
}
body {
  font-size: 13pt;
  color: gray;
  margin: 5px 25px;
}
pre {
  border: solid 3px #ddd;
  padding: 10px;
}
tr {
  margin: 5px;
}
th {
  padding: 5px;
  color: white;
  background: darkgray;
}
td {
  padding: 5px;
  color: black;
  background: #f0f0f0;
}
.err {
  color: red;
}
</style>
</head>
<body>

<h1>ミュージックプレイヤー</h1>
<p th:text="${msg}"></p>
<form method="post" action="/" th:object="${formModel}">
  <table>
    <tr>
      <td><label for="title">タイトル</label></td>
      <td>
        <input type="text" name="title" th:value="*{title}"
      			th:errorclass="err" />
      	<div th:if="${#fields.hasErrors('title')}" th:errors="*{title}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td><label for="artist">アーティスト</label></td>
      <td>
        <input type="text" name="artist" th:value="*{artist}"
      			th:errorclass="err"/>
      	<div th:if="${#fields.hasErrors('artist')}" th:errors="*{artist}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td><label for="playlist">プレイリスト</label></td>
      <td>
        <input type="text" name="playlist" th:value="*{playlist}"
      			th:errorclass="err"/>
      	<div th:if="${#fields.hasErrors('playlist')}" th:errors="*{playlist}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" /></td>
    </tr>
  </table>
</form>

<hr />
<table>
  <tr>
    <th>ID</th><th>タイトル</th><th>アーティスト</th><th>編集</th><th>削除</th>
  </tr>
  <tr th:each="obj : ${datalist}">
    <td th:text="${obj.id}"></td>
    <td th:text="${obj.title}"></td>
    <td th:text="${obj.artist}"></td>
    <td><a th:href="@{'/edit/' + ${obj.id}}">編集</a></td>
    <td><a th:href="@{'/delete/' + ${obj.id}}">削除</a></td>
  </tr>
</table>

</body>
</html>

入力フォームの下に、Musicのリストを表示しているが、そこにプレイリスト名を表示する。
プレイリストがnullの場合は「プレイリストなし」と表示する。

<hr />
<table>
  <tr>
    <th>ID</th><th>タイトル</th><th>アーティスト</th><th>プレイリスト</th><th>編集</th><th>削除</th>
  </tr>
  <tr th:each="obj : ${datalist}">
    <td th:text="${obj.id}"></td>
    <td th:text="${obj.title}"></td>
    <td th:text="${obj.artist}"></td>
    <td th:if="${obj.playlist != null}" th:text="${obj.playlist.name}"></td>
    <td th:if="${obj.playlist == null}" th:text="プレイリストなし"></td>
    <td><a th:href="@{'/edit/' + ${obj.id}}">編集</a></td>
    <td><a th:href="@{'/delete/' + ${obj.id}}">削除</a></td>
  </tr>
</table>

Musicを編集できるようにする。

コントローラで編集のURLを受け付けるようにする。

	@RequestMapping(value = "/edit/{id}")
	public ModelAndView edit(@ModelAttribute Music music,
			@PathVariable long id,
			ModelAndView mav) {
		mav.setViewName("edit");
		mav.addObject("title", "edit music");
		Optional<Music> data = repository.findById(id);
		mav.addObject("formModel", data.get());
		return mav;
	}

HTMLテンプレート edit.html を作成する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>top page</title>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
<style type="text/css">
h1 {
  font-size: 18pt;
  font-weight: bold;
  color: gray;
}
body {
  font-size: 13pt;
  color: gray;
  margin: 5px 25px;
}
pre {
  border: solid 3px #ddd;
  padding: 10px;
}
tr {
  margin: 5px;
}
th {
  padding: 5px;
  color: white;
  background: darkgray;
}
td {
  padding: 5px;
  color: black;
  background: #f0f0f0;
}
</style>
</head>
<body>

<h1>Music edit page</h1>

<form method="post" action="/edit" th:object="${formModel}">
  <input type="hidden" name="id" th:value="*{id}" />
  <table>
    <tr>
      <td><label for="title">タイトル</label></td>
      <td><input type="text" name="title" th:value="*{title}" /></td>
    </tr>
    <tr>
      <td><label for="artist">アーティスト</label></td>
      <td><input type="text" name="artist" th:value="*{artist}" /></td>
    </tr>
    <tr>
      <td><label for="playlist">プレイリスト</label></td>
      <td th:if="*{playlist != null}">
        <input type="text" name="playlist" th:value="*{playlist.id}" />
      </td>
      <td th:if="*{playlist == null}">
        <input type="text" name="playlist" value="" />
      </td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" /></td>
    </tr>
  </table>
</form>


</body>
</html>

MusicController で POSTを受け付ける。

	@RequestMapping(value = "/edit", method = RequestMethod.POST)
	public ModelAndView form(@ModelAttribute @Validated Music music,
			Errors result,
			ModelAndView mav) {
		if (result.hasErrors()) {
			return mav;
		}
		repository.saveAndFlush(music);
		return new ModelAndView("redirect:/");
	}

7月2日

ミュージックプレイヤーのWebアプリケーションを作ってみる

以前、JavaコンソールアプリケーションとしてMusicPlayerを作成したが、今回は、それをSpringBootを使用したWebアプリケーションとして作成してみる。

まずは新規プロジェクトを作成する。

プロジェクト名は好きなように決めてよい。

pom.xml で SpringBoot のバージョンを変更する。
デフォルトでは2.1.6になっているが、エラーが発生するので、これまでに使っていた2.1.4にする。
そして、ThymeleafとJPAとHSQLDBの依存関係も追加しておく。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>jp.abc</groupId>
	<artifactId>stunes</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>stunes</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

HSQLDBを起動するBATファイルに、新しいデータベースインスタンスを追加する。

cd C:\pleiades\hsqldb-2.4.1\hsqldb\lib
java -cp hsqldb.jar org.hsqldb.Server --database.0 db/mydata --dbname.0 mydata --database.1 db/stunes --dbname.1 stunes

Musicエンティティを作成する。

package jp.abc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class Music {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	private long id;

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

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

	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;
	}

	@Override
	public String toString() {
		return "Music [title=" + title + ", artist=" + artist + "]";
	}

}

リポジトリを作成する。

package jp.abc;

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

public interface MusicRepository extends JpaRepository<Music, Long> {

}

コントローラを作成する。

package jp.abc;

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 MusicController {

	@Autowired
	private MusicRepository repository;

	@RequestMapping("/")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		return mav;
	}
}

HTMLテンプレートを作成する。
CSSと入力フォームの部分は、mydata.html の該当箇所をコピーして使うと早い。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ミュージックプレイヤー</title>
<style type="text/css">
h1 {
  font-size: 18pt;
  font-weight: bold;
  color: gray;
}
body {
  font-size: 13pt;
  color: gray;
  margin: 5px 25px;
}
pre {
  border: solid 3px #ddd;
  padding: 10px;
}
tr {
  margin: 5px;
}
th {
  padding: 5px;
  color: white;
  background: darkgray;
}
td {
  padding: 5px;
  color: black;
  background: #f0f0f0;
}
.err {
  color: red;
}
</style>
</head>
<body>

<h1>ミュージックプレイヤー</h1>
<p th:text="${msg}"></p>
<form method="post" action="/" th:object="${formModel}">
  <table>
    <tr>
      <td><label for="title">タイトル</label></td>
      <td>
        <input type="text" name="title" th:value="*{title}"
      			th:errorclass="err" />
      	<div th:if="${#fields.hasErrors('title')}" th:errors="*{title}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td><label for="artist">アーティスト</label></td>
      <td>
        <input type="text" name="artist" th:value="*{artist}"
      			th:errorclass="err"/>
      	<div th:if="${#fields.hasErrors('artist')}" th:errors="*{artist}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" /></td>
    </tr>
  </table>
</form>

</body>
</html>

これで実行するとエラーが発生する。
コントローラで formModel を渡していないのが原因なので、コントローラを修正する。

package jp.abc;

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 MusicController {

	@Autowired
	private MusicRepository repository;

	@RequestMapping("/")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		Music m = new Music();
		mav.addObject("formModel", m);
		return mav;
	}
}

POSTメソッドを受け付けるようにするために、コントローラを修正する。

package jp.abc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.annotation.Validated;
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 MusicController {

	@Autowired
	private MusicRepository repository;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		Music m = new Music();
		mav.addObject("formModel", m);
		return mav;
	}

	@RequestMapping(value = "/", method = RequestMethod.POST)
	public ModelAndView post(
			@ModelAttribute("formModel") @Validated Music music,
			Errors result,
			ModelAndView mav) {
		if (result.hasErrors()) {
			mav.setViewName("index");
			mav.addObject("msg", "エラーです");
			return mav;
		}
		repository.saveAndFlush(music);
		return new ModelAndView("redirect:/");
	}
}

データベース接続の設定を、application.properties ファイルに記述する。

spring.datasource.url=jdbc:hsqldb:hsql://localhost/stunes
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.jpa.hibernate.ddl-auto=update

HTMLテンプレートに、保存されているデータのリストを表示するテーブルを追加する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ミュージックプレイヤー</title>
<style type="text/css">
h1 {
  font-size: 18pt;
  font-weight: bold;
  color: gray;
}
body {
  font-size: 13pt;
  color: gray;
  margin: 5px 25px;
}
pre {
  border: solid 3px #ddd;
  padding: 10px;
}
tr {
  margin: 5px;
}
th {
  padding: 5px;
  color: white;
  background: darkgray;
}
td {
  padding: 5px;
  color: black;
  background: #f0f0f0;
}
.err {
  color: red;
}
</style>
</head>
<body>

<h1>ミュージックプレイヤー</h1>
<p th:text="${msg}"></p>
<form method="post" action="/" th:object="${formModel}">
  <table>
    <tr>
      <td><label for="title">タイトル</label></td>
      <td>
        <input type="text" name="title" th:value="*{title}"
      			th:errorclass="err" />
      	<div th:if="${#fields.hasErrors('title')}" th:errors="*{title}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td><label for="artist">アーティスト</label></td>
      <td>
        <input type="text" name="artist" th:value="*{artist}"
      			th:errorclass="err"/>
      	<div th:if="${#fields.hasErrors('artist')}" th:errors="*{artist}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" /></td>
    </tr>
  </table>
</form>

<hr />
<table>
  <tr>
    <th>ID</th><th>タイトル</th><th>アーティスト</th><th>編集</th><th>削除</th>
  </tr>
  <tr th:each="obj : ${datalist}">
    <td th:text="${obj.id}"></td>
    <td th:text="${obj.title}"></td>
    <td th:text="${obj.artist}"></td>
    <td><a th:href="@{'/edit/' + ${obj.id}}">編集</a></td>
    <td><a th:href="@{'/delete/' + ${obj.id}}">削除</a></td>
  </tr>
</table>

</body>
</html>

コントローラで、datalist の名前で、データをわたす。

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		Music m = new Music();
		mav.addObject("formModel", m);
		List<Music> list = repository.findAll();
		mav.addObject("datalist", list);
		return mav;
	}

プレイリストも作ってみる

まずはエンティティを作成する。

package jp.abc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class PlayList {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	private long id;

	@Column(length = 200, nullable = false)
	@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;
	}


}

HTMLテンプレートを作成する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>プレイリスト</title>
<style type="text/css">
h1 {
  font-size: 18pt;
  font-weight: bold;
  color: gray;
}
body {
  font-size: 13pt;
  color: gray;
  margin: 5px 25px;
}
pre {
  border: solid 3px #ddd;
  padding: 10px;
}
tr {
  margin: 5px;
}
th {
  padding: 5px;
  color: white;
  background: darkgray;
}
td {
  padding: 5px;
  color: black;
  background: #f0f0f0;
}
.err {
  color: red;
}
</style>
</head>
<body>

<h1>プレイリスト</h1>
<p th:text="${msg}"></p>
<form method="post" action="/" th:object="${formModel}">
  <table>
    <tr>
      <td><label for="name">名前</label></td>
      <td>
        <input type="text" name="name" th:value="*{name}"
      			th:errorclass="err" />
      	<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}"
      		th:errorclass="err"></div>
      </td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" /></td>
    </tr>
  </table>
</form>

<hr />
<table>
  <tr>
    <th>ID</th><th>名前</th>
  </tr>
  <tr th:each="obj : ${datalist}">
    <td th:text="${obj.id}"></td>
    <td th:text="${obj.title}"></td>
  </tr>
</table>

</body>
</html>

コントローラを作成する。

package jp.abc;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class PlayListController {
	@RequestMapping("/playlist")
	public ModelAndView list(ModelAndView mav) {
		mav.setViewName("playlist");
		PlayList pl = new PlayList();
		mav.addObject("formModel", pl);
		return mav;
	}
}

動いた!