问题描述
我能够将书籍和作者保存到数据库中。在编辑条目的内容(书名,体裁和作者)时,我松开了作者的部分。在“编辑”页面中,使用下拉列表显示作者列表。这个想法是必须选择一个特定的作者,直到用户更改它为止。
这是Book的控制器和模板。
@RequestMapping(path = {"/edit","/edit/{id}"})
public String editBookById(Model model,@PathVariable("id")
Optional<Long>id)
throws NotFoundException
{
if (id.isPresent()) {
Optional<Book> response = bookRepository.findById(id.get());
if(!response.isPresent()){
throw new NotFoundException("Book not found.");
// return "not-found";
}
Book book = response.get();
model.addAttribute("book",book);
} else {
model.addAttribute("book",new Book());
}
model.addAttribute("authors",authorRepository.findAll());
return "books/add-edit";
}
模板:
<form action="@/books/edit" th:object="${book}" method='POST'>
<table>
<tr>
<td>Select Authors:</td>
<td>
<select id="authorsList" name="authors" field="*{author}"><!---1,2,3,4,5--><!---the secret-->
<!--<option value="Author">Author</option>-->
<option th:each="author :${authors}"
th:value="${author.firstName}"
th:text="${author.firstName}+' '+${author.id}"
th:selected="${author}">
</option>
</select>
</td>
</tr>
</table>
</form>
解决方法
如果要实现表单的编辑,则需要实现GetMapping
和PostMapping
(两者都是RequestMapping
的元注释)。
当浏览器首先显示该表单时,它会执行GET。控制器中支持该方法的方法应类似于:
@GetMapping("/edit/{id}")
public String showEditForm(Model model,@PathVariable("id") Long id) {
Book book = bookRepository.findById(id).orElseThrow( ()-> new NotFoundException("Book not found. Id: " + id));
model.addAttribute("book",book);
model.addAttribute("authors",authorRepository.findAll());
return "books/add-edit";
}
提交表单时,会发生POST,因此您需要@PostMapping
。像这样:
@PostMapping("/edit/{id}")
public String doEditBook(@PathVariable("id") Long id,@Valid @ModelAttribute("book") Book book,BindingResults bindingResults,Model model) {
if(bindingResults.hasErrors()) {
model.addAttribute("authors",authorRepository.findAll());
return "books/add-edit"
}
// save book updates in db here
bookService.updateBook(book);
return "redirect:/books";
}
但是,直接在表单中使用Book
实体通常是个坏主意。最好创建一个DTO,像EditBookFormData
这样直接映射到表单字段:
public class EditBookFormData {
private Long id; // this is the id of the book itself
private Long authorId;
// other fields here
public static EditBookFormData fromBook(Book book) {
// create a new EditBookFormData instance here and populate the fields
}
}
更新后的GetMapping
变为:
@GetMapping("/edit/{id}")
public String showEditForm(Model model,EditBookFormData.fromBook(book));
model.addAttribute("authors",authorRepository.findAll());
return "books/add-edit";
}
POST变为:
@PostMapping("/edit/{id}")
public String doEditBook(@PathVariable("id") Long id,@Valid @ModelAttribute("book") EditBookFormData formData,authorRepository.findAll());
return "books/add-edit"
}
// save book updates in db here
bookService.updateBook(formData);
return "redirect:/books";
}
和模板:
<form action="@/books/edit" th:object="${book}" method='POST'>
<table>
<tr>
<td>Select Authors:</td>
<td>
<select id="authorsList" name="authors" th:field="*{authorId}">
<option th:each="author :${authors}"
th:value="${author.id}"
th:text="${author.firstName}+' '+${author.lastName}">
</option>
</select>
</td>
</tr>
</table>
</form>