本を別の本棚に移動しようとするとエラーになってしまう。
これは、今の状態では1冊の本を複数の本棚に入れようとしている。
現実的に不可能なことをやろうとしているのでエラーになる。
本棚を移動するためには、元の本棚から本を取り出した後で、別の本棚に移動するという操作が必要になる。
package jp.bookshelf; 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.ModelAttribute; 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; @Autowired private BookshelfRepository bookshelfRepository; @RequestMapping(value = "/book", method = RequestMethod.GET) public ModelAndView list(ModelAndView mav) { mav.addObject("book", new Book()); mav.setViewName("books"); List<Book> list = repository.findAll(); List<Bookshelf> bookshelfs = bookshelfRepository.findAll(); mav.addObject("list", list); mav.addObject("bookshelfs", bookshelfs); return mav; } @RequestMapping(value = "/book", method = RequestMethod.POST) public ModelAndView post(ModelAndView mav, @ModelAttribute("book") Book book) { repository.saveAndFlush(book); return new ModelAndView("redirect:/book"); } @RequestMapping(value = "/edit/{id}", method = RequestMethod.GET) public ModelAndView edit(ModelAndView mav, @PathVariable long id) { mav.setViewName("edit"); Optional<Book> data = repository.findById(id); mav.addObject("book", data.get()); return mav; } @RequestMapping(value = "/edit", method = RequestMethod.POST) public ModelAndView update(ModelAndView mav, @ModelAttribute("book") Book book) { repository.saveAndFlush(book); return new ModelAndView("redirect:/book"); } @RequestMapping(value = "/push", method = RequestMethod.POST) public ModelAndView push(ModelAndView mav, @RequestParam("id") long id, @RequestParam("bookshelf") long bookshelfId) { Optional<Book> data = repository.findById(id); Book book = data.get(); Bookshelf prev = book.getBookshelf(); if (prev != null) { prev.removeBook(book); bookshelfRepository.saveAndFlush(prev); } if (bookshelfId != 0) { Optional<Bookshelf> bs = bookshelfRepository.findById(bookshelfId); Bookshelf bookshelf = bs.get(); bookshelf.addBook(book); book.setBookshelf(bookshelf); bookshelfRepository.saveAndFlush(bookshelf); repository.saveAndFlush(book); } else { book.setBookshelf(null); repository.saveAndFlush(book); return new ModelAndView("redirect:/"); } return new ModelAndView("redirect:/bookshelf/" + bookshelfId); } }
本を本棚に入れた後で、本棚から取り出して、どの本棚にも入れないという操作もできるようにする。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>本のリスト</title> <style type="text/css"> img.book-image { width: 100px; } </style> </head> <body> <h2>本を追加</h2> <form action="/book" method="post" th:object="${book}"> タイトル: <input type="text" name="title" th:value="*{title}" /> <br /> 著者: <input type="text" name="author" th:value="*{author}" /> <br /> 画像URL: <input type="text" name="image" th:value="*{image}" /> <br /> <input type="submit" value="本を追加" /> </form> <h1>本のリスト</h1> <table> <tr> <th>画像</th><th>タイトル</th><th>著者名</th><th>操作</th><th>本棚</th> </tr> <tr th:each="book : ${list}"> <td><img class="book-image" th:src="${book.image}" /></td> <td th:text="${book.title}"></td> <td th:text="${book.author}"></td> <td> <a th:href="@{'/edit/' + ${book.id}}">修正</a> <a th:href="@{'/delete/' + ${book.id}}">削除</a> </td> <td> 今の本棚: <span th:if="${book.bookshelf != null}" th:text="${book.bookshelf.name}"></span> <form action="/push" method="post"> <input type="hidden" name="id" th:value="${book.id}" /> <select name="bookshelf"> <option value="0">本棚に入れない</option> <th:block th:each="bookshelf : ${bookshelfs}"> <option th:value="${bookshelf.id}" th:text="${bookshelf.name}"></option> </th:block> </select>に<button>移動</button>する <p th:if="${book.bookshelf != null}" th:text="${book.bookshelf.name}"> </form> </td> </tr> </table> <a href="/">戻る</a> </body> </html>
BookshelfにremoveBook()を追加する。
public void addBook(Book book) { books.add(book); } public void removeBook(Book book) { books.remove(book); } }