Bookshelfアプリを作成する (Delete)

book.html テンプレートに削除確認画面へのリンクを追加する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本を入れる本棚を指定する</title>
</head>
<body>

<h1>Book</h1>

<a href="/">トップ</a>


<table>
	<tr><td><img th:src="${book.image}" width="100" /></td></tr>
	<tr>
		<td th:text="${book.title}"></td>
		<td th:text="${book.author}"></td>
		<td><a th:href="@{'/book/edit/' + ${book.id}}" th:text="修正"></a></td>
		<td><a th:href="@{'/book/delete/' + ${book.id}}" th:text="削除"></a></td>
	</tr>
</table>

<hr />

<div>どの本棚に入れますか?</div>
<form action="/book" method="post">
	<input type="hidden" name="id" th:value="${book.id}" />
	<div>
		<select name="bookshelfId">
			<option value="0">本棚に入れない</option>
			<option th:each="bs : ${bookshelfList}" th:value="${bs.id}" th:selected="${bs.id == book.id}" th:text="${bs.name}"></option>
		</select>
	</div>
	<div><input id="submit" type="submit" value="本棚に入れる" /></div>
</form>


</body>
</html>

コントローラに削除確認画面に対応するURLマッピングを追加する。

	@RequestMapping(value = "/book/delete/{id}", method = RequestMethod.GET)
	public ModelAndView deleteConfirm(ModelAndView mav,
			@PathVariable long id) {
		mav.setViewName("deletebook");
		Optional<Book> data = repository.findById(id);
		mav.addObject("book", data.get());
		return mav;
	}

削除確認画面になる deletebook.html テンプレートを追加する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本を削除する</title>
</head>
<body>

<h1>本の削除確認</h1>

<a href="/">トップ</a>


<table>
	<tr><td><img th:src="${book.image}" width="100" /></td></tr>
	<tr>
		<td th:text="${book.title}"></td>
		<td th:text="${book.author}"></td>
	</tr>
</table>
<form action="/book/delete" method="post">
	<input type="hidden" name="id" th:value="${book.id}" />
	<div><input id="submit" type="submit" value="削除する" /></div>
</form>


</body>
</html>

POSTメソッドで本の削除を実行する。

	@RequestMapping(value = "/book/delete", method = RequestMethod.POST)
	public ModelAndView delete(ModelAndView mav,
			@RequestParam("id") long id) {
		repository.deleteById(id);
		return new ModelAndView("redirect:/books");
	}

Bookshelfアプリを作成する (Update)

CRUDのうち、CreateとReadは動いているので、次はUpdateを作ってみる。

BookContoller.java

	@RequestMapping(value = "/book/edit/{id}", method = RequestMethod.GET)
	public ModelAndView edit(ModelAndView mav,
			@PathVariable long id) {
		mav.setViewName("editbook");
		Optional<Book> data = repository.findById(id);
		mav.addObject("book", data.get());
		List<Bookshelf> list = bookshelfRepository.findAll();
		mav.addObject("bookshelfList", list);
		return mav;
	}

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

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

<a href="/">トップ</a>

<h1>本の編集</h1>

<form action="/book/edit" method="post">
	<div>タイトル: <input type="text" name="title" th:value="${book.title}" /></div>
	<div>著者: <input type="text" name="author" th:value="${book.author}" /></div>
	<div><input id="submit" type="submit" value="修正" /></div>
</form>


</body>
</html>

サーバーを再起動して /book/edit/{id} にアクセスすると、本の編集画面を表示する。

POSTメソッドのリクエストを受け取るところは作ってないので「修正」ボタンを押すとエラーになる。

コントローラでPOSTメソッドを受け取れるようにする。

	@RequestMapping(value = "/book/edit", method = RequestMethod.POST)
	public ModelAndView edit(ModelAndView mav,
			@RequestParam("id") long id,
			@RequestParam("title") String title,
			@RequestParam("author") String author) {
		Optional<Book> data = repository.findById(id);
		Book book = data.get();
		book.setTitle(title);
		book.setAuthor(author);
		repository.saveAndFlush(book);
		return new ModelAndView("redirect:/book/" + id);
	}

再起動して「修正」ボタンを押すとエラー表示になる。
エラーメッセージを読むと、リクエストパラメータにidが存在しないと言っているので、入力フォームに追加する。

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

<a href="/">トップ</a>

<h1>本の編集</h1>

<form action="/book/edit" method="post">
	<input type="hidden" name="id" th:value="${book.id}" />
	<div>タイトル: <input type="text" name="title" th:value="${book.title}" /></div>
	<div>著者: <input type="text" name="author" th:value="${book.author}" /></div>
	<div><input id="submit" type="submit" value="修正" /></div>
</form>


</body>
</html>

book.html に修正画面へのリンクを追加する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本を入れる本棚を指定する</title>
</head>
<body>

<h1>Book</h1>

<a href="/">トップ</a>

<table>
	<tr>
		<td th:text="${book.title}"></td>
		<td th:text="${book.author}"></td>
		<td><a th:href="@{'/book/edit/' + ${book.id}}" th:text="修正"></a></td>
	</tr>
</table>
:

本の画像を表示できるようにする。

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 Book {
	@Id
	@GeneratedValue
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String title;

	@Column
	@NotEmpty
	private String author;

	@Column
	private String image;

	@ManyToOne
	private Bookshelf bookshelf;

	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 getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public Bookshelf getBookshelf() {
		return bookshelf;
	}

	public void setBookshelf(Bookshelf bookshelf) {
		this.bookshelf = bookshelf;
	}

	public String getImage() {
		return image;
	}

	public void setImage(String image) {
		this.image = image;
	}

}

コントローラで画像URLも保存するように修正する。

	@RequestMapping(value = "/book/edit", method = RequestMethod.POST)
	public ModelAndView edit(ModelAndView mav,
			@RequestParam("id") long id,
			@RequestParam("title") String title,
			@RequestParam("author") String author,
			@RequestParam("image") String image) {
		Optional<Book> data = repository.findById(id);
		Book book = data.get();
		book.setTitle(title);
		book.setAuthor(author);
		book.setImage(image);
		repository.saveAndFlush(book);
		return new ModelAndView("redirect:/book/" + id);
	}

editbook.html テンプレート内で画像を表示する。

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

<a href="/">トップ</a>

<h1>本の編集</h1>

<img th:src="${book.image}" width="200" />

<form action="/book/edit" method="post">
	<input type="hidden" name="id" th:value="${book.id}" />
	<div>タイトル: <input type="text" name="title" th:value="${book.title}" /></div>
	<div>著者: <input type="text" name="author" th:value="${book.author}" /></div>
	<div>画像URL: <input type="text" name="image" th:value="${book.image}" /></div>
	<div><input id="submit" type="submit" value="修正" /></div>
</form>


</body>
</html>

book.html テンプレートにも画像を追加。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本を入れる本棚を指定する</title>
</head>
<body>

<h1>Book</h1>

<a href="/">トップ</a>


<table>
	<tr><td><img th:src="${book.image}" width="100" /></td></tr>
	<tr>
		<td th:text="${book.title}"></td>
		<td th:text="${book.author}"></td>
		<td><a th:href="@{'/book/edit/' + ${book.id}}" th:text="修正"></a></td>
	</tr>
</table>
:

books.html テンプレートにも画像を追加。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本のリスト</title>
</head>
<body>

<h1>Book list</h1>

<a href="/">トップ</a>

<table>
	<tr>
		<th>ID</th><th>画像</th><th>タイトル</th><th>著者</th><th>本棚</th>
	</tr>
	<tr th:each="book : ${list}">
		<td th:text="${book.id}"></td>
		<td><img th:src="${book.image}" height="50" /></td>
		<td><a th:href="@{'/book/' + ${book.id}}" th:text="${book.title}"></a></td>
		<td th:text="${book.author}"></td>
		<td th:if="${book.bookshelf != null}" th:text="${book.bookshelf.name}"></td>
		<td th:if="${book.bookshelf == null}" th:text="本棚に入れてません"></td>
	</tr>
</table>

Bookshelfアプリを作成する

新規プロジェクトを作成する。
プロジェクトの種類は、Springスターター・プロジェクトを選択する。

プロジェクト名を「bookshelf」にして次へをクリック。

依存関係は、以下の項目を選択する。

  • HyperSQL Database
  • Spring Data JPA
  • Spring Web
  • Thymeleaf

「完了」でbookshelfプロジェクトができる。

pom.xml を開いて、8行目のバージョンを2.2.1に修正する。

		<version>2.2.1.RELEASE</version>

[実行]-[Spring Boot アプリケーション]を選択するとサーバーが起動する。

http://localhost:8080 にアクセスすると、Whitelabel Error Page が表示される。

IndexControler.java を作成する。

package jp.kpc;

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

@Controller
public class IndexController {

	@RequestMapping("/")
	public String index() {
		return "index";
	}

}

example プロジェクトの index.html をコピーして、src/main/resources の templates に貼り付ける。

SpringBootアプリケーションを再起動すると、「最初のページ」が表示される。

application.properties にデータベース接続設定を追加する。

spring.datasource.url=jdbc:hsqldb:hsql://localhost/bookshelf
spring.datasource.username=SA
spring.datasource.password=
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.jpa.hibernate.ddl-auto=update

hsqldb.bat に bookshelf インスタンスを追加する。

cd data
java -classpath ../lib/hsqldb.jar org.hsqldb.server.Server ^
--database.0 db/shindan --dbname.0 shindan ^
--database.1 db/bookshelf --dbname.1 bookshelf

index.html に、新しい本棚を追加するためのフォームを用意する。

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

<h1>Bookshelf list</h1>

<hr />

<div>新しい本棚</div>
<form action="/addshelf" method="post">
	<div>なまえ</div>
	<div><input type="text" name="name" /></div>
	<div><input id="submit" type="submit" value="+追加" /></div>
</form>


</body>
</html>

IndexController.java に /addshelf に対する POST を受け取る用意をする。POSTを受け取ったあとは、URL=”/” にリダイレクトする。

package jp.kpc;

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

@Controller
public class IndexController {

	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value="/addshelf", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("name") String name) {
		return new ModelAndView("redirect:/");
	}
}

本棚に対応する Bookshelf クラスを作成する。

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 Bookshelf {
	@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;
	}

}

新規インターフェースを作成する。
BookshelfRepository.java

package jp.kpc;

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

public interface BookshelfRepository extends JpaRepository<Bookshelf, Long> {

}

IndexController.java で、リクエストパラメータで渡された名前の本棚を保存する処理を追加する。

package jp.kpc;

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

@Controller
public class IndexController {

	@Autowired
	private BookshelfRepository repository;

	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value="/addshelf", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("name") String name) {
		Bookshelf bookshelf = new Bookshelf();
		bookshelf.setName(name);
		repository.saveAndFlush(bookshelf);
		return new ModelAndView("redirect:/");
	}
}

トップページにアクセスがあったときに、本棚リストをテンプレートに渡す。

IndexController.java

@Controller
public class IndexController {

	@Autowired
	private BookshelfRepository repository;

	@RequestMapping("/")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		List<Bookshelf> list = repository.findAll();
		mav.addObject("list", list);
		return mav;
	}

テンプレートで本棚のリストを表示する。

index.html

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

<h1>Bookshelf list</h1>
<table>
	<tr th:each="bs : ${list}">
		<td th:text="${bs.name}"></td>
	</tr>
</table>

<hr />

<div>新しい本棚</div>
<form action="/addshelf" method="post">
	<div>なまえ</div>
	<div><input type="text" name="name" /></div>
	<div><input id="submit" type="submit" value="+追加" /></div>
</form>


</body>
</html>

Bookクラスを作成する。

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 Book {
	@Id
	@GeneratedValue
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String title;

	@Column
	@NotEmpty
	private String author;

	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 getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}


}

BookController.java

package jp.kpc;

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

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

}

books.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本のリスト</title>
</head>
<body>

<h1>Book list</h1>
<table>
	<tr th:each="book : ${list}">
		<td th:text="${book.title}"></td>
		<td th:text="${book.author}"></td>
	</tr>
</table>

<hr />

<div>新しい本</div>
<form action="/addbook" method="post">
	<div>タイトル: <input type="text" name="title" /></div>
	<div>著者: <input type="text" name="author" /></div>
	<div><input id="submit" type="submit" value="+追加" /></div>
</form>


</body>
</html>

BookRepository.java

package jp.kpc;

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

public interface BookRepository extends JpaRepository<Book, Long> {

}

リポジトリを用意したので、それをBookControllerで使う。

package jp.kpc;

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.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class BookController {
	@Autowired
	private BookRepository repository;

	@RequestMapping("/books")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("books");
		List<Book> list = repository.findAll();
		mav.addObject("list", list);
		return mav;
	}

	@RequestMapping(value="/addbook", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("title") String title,
			@RequestParam("author") String author) {
		Book book = new Book();
		book.setTitle(title);
		book.setAuthor(author);
		repository.saveAndFlush(book);
		return new ModelAndView("redirect:/books");
	}
}

本と本棚の関連付けを作る。

Bookshelf.java

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 Bookshelf {
	@Id
	@GeneratedValue
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String name;

	@OneToMany
	private List<Book> books;

	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<Book> getBooks() {
		return books;
	}

	public void setBooks(List<Book> books) {
		this.books = books;
	}

}

Book.java

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 Book {
	@Id
	@GeneratedValue
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String title;

	@Column
	@NotEmpty
	private String author;

	@ManyToOne
	private Bookshelf bookshelf;

	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 getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public Bookshelf getBookshelf() {
		return bookshelf;
	}

	public void setBookshelf(Bookshelf bookshelf) {
		this.bookshelf = bookshelf;
	}
}

本を入れる本棚を指定するための画面を作る。
そのために、/book/{id} (idはBookのid)というURLを用意する。

package jp.kpc;

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.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class BookController {
	@Autowired
	private BookRepository repository;

	@RequestMapping("/books")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("books");
		List<Book> list = repository.findAll();
		mav.addObject("list", list);
		return mav;
	}

	@RequestMapping(value="/addbook", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("title") String title,
			@RequestParam("author") String author) {
		Book book = new Book();
		book.setTitle(title);
		book.setAuthor(author);
		repository.saveAndFlush(book);
		return new ModelAndView("redirect:/books");
	}


	@RequestMapping(value = "/book/{id}", method = RequestMethod.GET)
	public ModelAndView book(ModelAndView mav,
			@PathVariable long id) {
		mav.setViewName("book");
		Optional<Book> data = repository.findById(id);
		mav.addObject("book", data.get());
		return mav;
	}

}

book.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本を入れる本棚を指定する</title>
</head>
<body>

<h1>Book</h1>
<table>
	<tr>
		<td th:text="${book.title}"></td>
		<td th:text="${book.author}"></td>
	</tr>
</table>

<hr />

<div>どの本棚に入れますか?</div>
<form action="/book" method="post">
	<input type="hidden" name="bookId" th:value="${book.id}" />
	<div>本棚ID: <input type="text" name="bookshelfId" /></div>
	<div><input id="submit" type="submit" value="本棚に入れる" /></div>
</form>


</body>
</html>

本と本棚の関連付けを保存する。

BookController.java

	@Autowired
	private BookshelfRepository bookshelfRepository;
	@RequestMapping(value="/book", method=RequestMethod.POST)
	public ModelAndView save(ModelAndView mav,
			@RequestParam("bookId") long bookId,
			@RequestParam("bookshelfId") long bookshelfId) {
		Optional<Book> data = repository.findById(bookId);
		Book book = data.get();
		Optional<Bookshelf> bsData = bookshelfRepository.findById(bookshelfId);
		Bookshelf bookshelf = bsData.get();
		book.setBookshelf(bookshelf);
		repository.saveAndFlush(book);
		return new ModelAndView("redirect:/books");
	}

books.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本のリスト</title>
</head>
<body>

<h1>Book list</h1>
<table>
	<tr>
		<th>ID</th><th>タイトル</th><th>著者</th><th>本棚</th>
	</tr>
	<tr th:each="book : ${list}">
		<td th:text="${book.id}"></td>
		<td th:text="${book.title}"></td>
		<td th:text="${book.author}"></td>
		<td th:if="${book.bookshelf != null}" th:text="${book.bookshelf.name}"></td>
		<td th:if="${book.bookshelf == null}" th:text="本棚に入れてません"></td>
	</tr>
</table>

<hr />

<div>新しい本</div>
<form action="/addbook" method="post">
	<div>タイトル: <input type="text" name="title" /></div>
	<div>著者: <input type="text" name="author" /></div>
	<div><input id="submit" type="submit" value="+追加" /></div>
</form>


</body>
</html>

本のタイトルをクリックしたら、/book/{id} に飛べるようにする。

<h1>Book list</h1>
<table>
	<tr>
		<th>ID</th><th>タイトル</th><th>著者</th><th>本棚</th>
	</tr>
	<tr th:each="book : ${list}">
		<td th:text="${book.id}"></td>
		<td><a th:href="@{'/book/' + ${book.id}}" th:text="${book.title}"></a></td>
		<td th:text="${book.author}"></td>
		<td th:if="${book.bookshelf != null}" th:text="${book.bookshelf.name}"></td>
		<td th:if="${book.bookshelf == null}" th:text="本棚に入れてません"></td>
	</tr>
</table>

本棚に入っている本のリストを表示する画面を作る。

/bookshelf/{id} で本棚内の本のリストを表示する。

bookshelf.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Bookshelf - 本棚に入っている本のリスト</title>
</head>
<body>

<h1>Bookshelf - 本棚に入っている本のリスト</h1>

<h3 th:text="${bookshelf.name}"></h3>

<ul th:each="book : ${bookshelf.books}">
	<li th:text="${book.title + ' - ' + book.author}"></li>
</ul>


</body>
</html>

Bookshelf.java

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

	@Column
	@NotEmpty
	private String name;

	@OneToMany(mappedBy = "bookshelf")
	private List<Book> books;

IndexController.java

	@RequestMapping(value = "/bookshelf/{id}", method = RequestMethod.GET)
	public ModelAndView bookshelf(ModelAndView mav,
			@PathVariable long id) {
		mav.setViewName("bookshelf");
		Optional<Bookshelf> data = repository.findById(id);
		mav.addObject("bookshelf", data.get());
		return mav;
	}

index.htmlのテーブルに列を追加して、本棚のIDを表示する。

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

<h1>Bookshelf list</h1>
<table>
	<tr th:each="bs : ${list}">
		<td th:text="${bs.id}"></td>
		<td th:text="${bs.name}"></td>
	</tr>
</table>

<hr />

<div>新しい本棚</div>
<form action="/addshelf" method="post">
	<div>なまえ</div>
	<div><input type="text" name="name" /></div>
	<div><input id="submit" type="submit" value="+追加" /></div>
</form>


</body>
</html>

本棚の名前をクリックしたら、本棚の内容を表示するページに移動できるようにする。
本のリストページ(/books)へのリンクも追加する。

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

<h1>Bookshelf list</h1>
<table>
	<tr th:each="bs : ${list}">
		<td th:text="${bs.id}"></td>
		<td><a th:href="@{'/bookshelf/' + ${bs.id}}" th:text="${bs.name}"></a></td>
	</tr>
</table>

<hr />

<div>新しい本棚</div>
<form action="/addshelf" method="post">
	<div>なまえ</div>
	<div><input type="text" name="name" /></div>
	<div><input id="submit" type="submit" value="+追加" /></div>
</form>

<a href="/books">本のリスト</a>


</body>
</html>

books.html、book.html、bookshelf.html に、トップページへのリンクを追加する。

books.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本のリスト</title>
</head>
<body>

<h1>Book list</h1>

<a href="/">トップ</a>

<table>
:

book.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本を入れる本棚を指定する</title>
</head>
<body>

<h1>Book</h1>

<a href="/">トップ</a>

<table>
:

bookshelf.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Bookshelf - 本棚に入っている本のリスト</title>
</head>
<body>

<h1>Bookshelf - 本棚に入っている本のリスト</h1>

<a href="/">トップ</a>

<h3 th:text="${bookshelf.name}"></h3>
:

本棚ページ内に表示した本のリストで、タイトルをクリックすると本のページに移動できるようにする。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Bookshelf - 本棚に入っている本のリスト</title>
</head>
<body>

<h1>Bookshelf - 本棚に入っている本のリスト</h1>

<a href="/">トップ</a>

<h3 th:text="${bookshelf.name}"></h3>

<ul th:each="book : ${bookshelf.books}">
	<li>
		<a th:href="@{'/book/' + ${book.id}}" th:text="${book.title}"></a>
		<span th:text="${' - ' + book.author}"></span>
	</li>
</ul>


</body>
</html>

book.html で、本棚IDを入力するのではなく、select で選択できるようにする。

BookController.java で、本棚のリストをテンプレートに渡すようにする。

	@RequestMapping(value = "/book/{id}", method = RequestMethod.GET)
	public ModelAndView book(ModelAndView mav,
			@PathVariable long id) {
		mav.setViewName("book");
		Optional<Book> data = repository.findById(id);
		mav.addObject("book", data.get());
		List<Bookshelf> list = bookshelfRepository.findAll();
		mav.addObject("bookshelfList", list);
		return mav;
	}

book.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Book - 本を入れる本棚を指定する</title>
</head>
<body>

<h1>Book</h1>

<a href="/">トップ</a>

<table>
	<tr>
		<td th:text="${book.title}"></td>
		<td th:text="${book.author}"></td>
	</tr>
</table>

<hr />

<div>どの本棚に入れますか?</div>
<form action="/book" method="post">
	<input type="hidden" name="bookId" th:value="${book.id}" />
	<div>
		<select name="bookshelfId">
			<option th:each="bs : ${bookshelfList}" th:value="${bs.id}" th:selected="${bs.id == book.id}" th:text="${bs.name}"></option>
		</select>
	</div>
	<div><input id="submit" type="submit" value="本棚に入れる" /></div>
</form>


</body>
</html>

本棚に入れない選択肢を追加する。

<div>どの本棚に入れますか?</div>
<form action="/book" method="post">
	<input type="hidden" name="bookId" th:value="${book.id}" />
	<div>
		<select name="bookshelfId">
			<option value="0">本棚に入れない</option>
			<option th:each="bs : ${bookshelfList}" th:value="${bs.id}" th:selected="${bs.id == book.id}" th:text="${bs.name}"></option>
		</select>
	</div>
	<div><input id="submit" type="submit" value="本棚に入れる" /></div>
</form>

コントローラでは、本棚検索して見つからないときは null を設定する。

	@RequestMapping(value="/book", method=RequestMethod.POST)
	public ModelAndView save(ModelAndView mav,
			@RequestParam("bookId") long bookId,
			@RequestParam("bookshelfId") long bookshelfId) {
		Optional<Book> data = repository.findById(bookId);
		Book book = data.get();
		Optional<Bookshelf> bsData = bookshelfRepository.findById(bookshelfId);
		if(bsData.isPresent()) {
			Bookshelf bookshelf = bsData.get();
			book.setBookshelf(bookshelf);
		} else {
			book.setBookshelf(null);
		}
		repository.saveAndFlush(book);
		return new ModelAndView("redirect:/books");
	}

Spring Bootを使ってWebアプリを作成する その3

Webアプリケーションを起動するたびにデータベースが初期化されてしまう設定になっていたので、それを修正する。

application.properties

spring.datasource.url=jdbc:hsqldb:hsql://localhost/shindan
spring.datasource.username=SA
spring.datasource.password=
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.jpa.hibernate.ddl-auto=update

IndexController.java

package jp.kpc;

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.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {
	@Autowired
	private ShindanRepository repository;

	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value="/form", method=RequestMethod.GET)
	public ModelAndView form(ModelAndView mav) {
		mav.setViewName("form");
		List<Shindan> list = repository.findAll();
		mav.addObject("list", list);
		return mav;
	}

	@RequestMapping(value="/form", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("name") String name,
			@RequestParam("eval") String eval) {
		int percent = (name + eval).hashCode() % 101;
		percent = Math.abs(percent);

		Shindan shindan = new Shindan();
		shindan.setName(name);
		shindan.setEval(eval);
		shindan.setPercent(percent);
		repository.saveAndFlush(shindan);
		String result = name + " さんの" + eval + "度は" + percent + "%です!!!";
		mav.addObject("result", result);

		List<Shindan> list = repository.findAll();
		mav.addObject("list", list);
		mav.setViewName("form");
		return mav;
	}

}

form.html

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

<h1>診断ページ</h1>

<p th:text="${result}"></p>

<form action="/form" method="post">
	おなまえ: <input type="text" name="name" />
	<br />
	診断: <input type="text" name="eval" />
	<input type="submit" value="診断" />
</form>

<hr />

<h3>これまでの診断結果</h3>
<table>
	<tr th:each="s : ${list}">
		<td th:text="${s.name} + ' さんの ' + ${s.eval} + '度は ' + ${s.percent} + '%です!!!'"></td>
	</tr>
</table>

</body>
</html>

CSSを使ってみる。

SpringBootの場合は、CSSファイルをsrc/main/resources の下の static 内に置く。

styles.css

@charset "UTF-8";

header {
	text-align: center;
	background: lightblue;
}

footer {
	text-align: center;
	background: lightblue;
}

form.html にヘッダーとフッターを追加する。
head要素内でCSSファイルを読み込む。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>診断ページ</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>

<header>
この部分はヘッダーですよ
</header>

<h1>診断ページ</h1>

<p th:text="${result}"></p>

<form action="/form" method="post">
	おなまえ: <input type="text" name="name" />
	<br />
	診断: <input type="text" name="eval" />
	<input type="submit" value="診断" />
</form>

<hr />

<h3>これまでの診断結果</h3>
<table>
	<tr th:each="s : ${list}">
		<td th:text="${s.name} + ' さんの ' + ${s.eval} + '度は ' + ${s.percent} + '%です!!!'"></td>
	</tr>
</table>


<footer>
この部分はフッターですよ
</footer>

</body>
</html>

入力フォーム部分などを中央寄せにする。

form.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>診断ページ</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>

<header>
この部分はヘッダーですよ
</header>

<h1>診断ページ</h1>

<p th:text="${result}"></p>

<form action="/form" method="post">
	<div>おなまえ</div>
	<div><input type="text" name="name" /></div>
	<div>なに度を診断しますか?</div>
	<div><input type="text" name="eval" /></div>
	<div><input id="submit" type="submit" value="診断" /></div>
</form>

<hr />

<h3>これまでの診断結果</h3>
<table>
	<tr th:each="s : ${list}">
		<td th:text="${s.name} + ' さんの ' + ${s.eval} + '度は ' + ${s.percent} + '%です!!!'"></td>
	</tr>
</table>


<footer>
この部分はフッターですよ
</footer>

</body>
</html>

styles.css

@charset "UTF-8";

header {
	text-align: center;
	background: #ffc107;
	color: white;
}

h1 {
	text-align: center;
	color: darkblue;
}

form {
	text-align: center;
}

footer {
	text-align: center;
	background: #ffc107;
	color: white;
}

#submit {
	background: lightgray;
	border: outset;
}

Spring Bootを使ってWebアプリを作成する その2

IndexControllerを作成する。
src/main/java の中にある jp.kpc を右クリックし[新規]-[クラス]を選択する。
名前に「IndexController」と入力し「完了」をクリック。

SpringBoot に対して、このクラスがコントローラであることを教えるために、@Controller アノテーションを追加する。
public class の前の行で「@Cont」を入力してCtrl+スペースを入力すると候補がリストアップされる。
org.springframework.stereotype のControllerを選択する。

package jp.kpc;

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

@Controller
public class IndexController {
	@RequestMapping("/")
	public String index() {
		return "index";
	}
}

SpringBootアプリケーションを起動して、 http://localhost:8080/ にアクセスすると、エラーになるが、先ほどと違うエラーになっていることがわかる。

エラーメッセージを読むと、indexテンプレートが見つからないという意味なので、次はテンプレートを作成する。

src/main/resources の下にある templates を右クリックして[新規]-[その他]を選択する。
「HTMLファイル」を選択し「次へ」をクリック。
ファイル名を index.html にして「次へ」をクリック。
「新規HTMLファイル(5)」を選択して「完了」をクリック。

もうひとつURLのパスを割り当てて、そちらでも index.html を表示してみる。

package jp.kpc;

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

@Controller
public class IndexController {
	@RequestMapping("/")
	public String index() {
		return "index";
	}

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

form.html

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

<h1>診断ページ</h1>

<form action="/form" method="post">
	おなまえ: <input type="text" name="name" />
	<br />
	診断: <input type="text" name="eval" />
	<input type="submit" value="診断" />
</form>


</body>
</html>

IndexController の form メソッドで指定しているテンプレートを form に変更する。

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

form メソッドは、GETメソッドだけ受け付けるように指定する。

	@RequestMapping(value="/form", method=RequestMethod.GET)
	public ModelAndView form(ModelAndView mav) {
		mav.setViewName("form");
		return mav;
	}

このように書き換えて再起動すると、http://localhost:8080/form へのアクセスは今まで通りに正常に動作するが、「診断」をクリックするとエラーになる。

form メソッドでGETメソッドだけを受け付けるようにしたために、POSTメソッドを受け取る場所がなくなった。

POSTを受け取るメソッドを用意する。

package jp.kpc;

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

@Controller
public class IndexController {
	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value="/form", method=RequestMethod.GET)
	public ModelAndView form(ModelAndView mav) {
		mav.setViewName("form");
		return mav;
	}

	@RequestMapping(value="/form", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav) {
		mav.setViewName("form");
		return mav;
	}

}

POSTメソッドでリクエストパラメータを受け取って、結果を渡してみる。

	@RequestMapping(value="/form", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("name") String name,
			@RequestParam("eval") String eval) {
		String result = name + " さんの" + eval + "度は?";
		mav.addObject("result", result);
		mav.setViewName("form");
		return mav;
	}

form.html に結果を表示するタグを追加する。

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

<h1>診断ページ</h1>

<p th:text="${result}"></p>

<form action="/form" method="post">
	おなまえ: <input type="text" name="name" />
	<br />
	診断: <input type="text" name="eval" />
	<input type="submit" value="診断" />
</form>


</body>
</html>

パーセンテージを計算して結果に追加する。

	@RequestMapping(value="/form", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("name") String name,
			@RequestParam("eval") String eval) {
		int percent = (name + eval).hashCode() % 101;
		percent = Math.abs(percent);
		String result = name + " さんの" + eval + "度は" + percent + "%です!!!";
		mav.addObject("result", result);
		mav.setViewName("form");
		return mav;
	}

過去の診断結果も表示できるようにする。

package jp.kpc;

import java.util.ArrayList;
import java.util.List;

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

@Controller
public class IndexController {
	private List<String> list = new ArrayList<String>();

	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value="/form", method=RequestMethod.GET)
	public ModelAndView form(ModelAndView mav) {
		mav.setViewName("form");
		return mav;
	}

	@RequestMapping(value="/form", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("name") String name,
			@RequestParam("eval") String eval) {
		int percent = (name + eval).hashCode() % 101;
		percent = Math.abs(percent);
		String result = name + " さんの" + eval + "度は" + percent + "%です!!!";
		list.add(result);
		mav.addObject("result", result);
		mav.addObject("list", list);
		mav.setViewName("form");
		return mav;
	}

}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>診断ページ</title>
</head>
<body>

<h1>診断ページ</h1>

<p th:text="${result}"></p>

<form action="/form" method="post">
	おなまえ: <input type="text" name="name" />
	<br />
	診断: <input type="text" name="eval" />
	<input type="submit" value="診断" />
</form>

<hr />

<h3>これまでの診断結果</h3>

<table>
	<tr th:each="result : ${list}">
		<td th:text="${result}"></td>
	</tr>
</table>

</body>
</html>

配布フォルダにある hsqldb フォルダをコピーしてZドライブの適当な場所に貼り付ける。
hsqldb フォルダ内の hsqldb.bat を編集する。

cd data
java -classpath ../lib/hsqldb.jar org.hsqldb.server.Server --database.0 db/shindan --dbname.0 shindan

データベースとの接続を行えるようにするために、pom.xml を編集する。

<?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 https://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.2.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>jp.kpc</groupId>
	<artifactId>example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>example</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>11</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<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>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</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>

src/main/resources にある application.properties ファイルを開き、以下の内容を記述する。

spring.datasource.url=jdbc:hsqldb:hsql://localhost/shindan
spring.datasource.username=SA
spring.datasource.password=
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver

jp.kpc を右クリックして[新規]-[クラス]を選択する。
名前に「Shindan」を入力して「完了」をクリック。

以下の内容を入力する。
Eclipseがアノテーションの補完をしてくれない場合は、pom.xml を保存してない可能性があるので、保存を確認!

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 Shindan {
	@Id
	@GeneratedValue
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String name;

	@Column
	@NotEmpty
	private String eval;

	@Column
	@NotNull
	private int percent;
}

メニューの[ソース]-[getterおよびsetterの生成]を選択する。
「すべて選択」をクリック。
挿入ポイントは「最後のメンバー」を選択し、「完了」をクリック。

すると、自動的にgetter/setter が追加される。

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 Shindan {
	@Id
	@GeneratedValue
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String name;

	@Column
	@NotEmpty
	private String eval;

	@Column
	@NotNull
	private int percent;

	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 getEval() {
		return eval;
	}

	public void setEval(String eval) {
		this.eval = eval;
	}

	public int getPercent() {
		return percent;
	}

	public void setPercent(int percent) {
		this.percent = percent;
	}
}

jp.kpc を右クリックして[新規]-[インターフェース]を選択する。
名前に「ShindanRepository」を入力。
拡張インターフェース「追加」をクリック。
JapRepository を選択して「OK」をクリック。
エラーが出ている T を Shindan に変更、ID を Long に変更して保存する。

package jp.kpc;

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

public interface ShindanRepository extends JpaRepository<Shindan, Long> {

}

コントローラにShindanをデータベースに保存するコードを追加する。

package jp.kpc;

import java.util.ArrayList;
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.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {
	private List<String> list = new ArrayList<String>();
	@Autowired
	private ShindanRepository repository;

	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value="/form", method=RequestMethod.GET)
	public ModelAndView form(ModelAndView mav) {
		mav.setViewName("form");
		return mav;
	}

	@RequestMapping(value="/form", method=RequestMethod.POST)
	public ModelAndView formPost(ModelAndView mav,
			@RequestParam("name") String name,
			@RequestParam("eval") String eval) {
		int percent = (name + eval).hashCode() % 101;
		percent = Math.abs(percent);

		Shindan shindan = new Shindan();
		shindan.setName(name);
		shindan.setEval(eval);
		shindan.setPercent(percent);
		repository.saveAndFlush(shindan);

		String result = name + " さんの" + eval + "度は" + percent + "%です!!!";
		list.add(result);
		mav.addObject("result", result);
		mav.addObject("list", list);
		mav.setViewName("form");
		return mav;
	}

}

診断をひとつやってみてから、データベースに接続してみる。
manager.bat をダブルクリックする。
Typeで「HSQL Database Engine Server」を選択する。
URLを「jdbc:hsqldb:hsql://localhost/shindan」にして「OK」をクリック。