java—如何在一对多关系中处理thymeleaf和spring中的表单?

mo49yndu  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(395)

这些是下面的模型。我省略了模型的getter和setter。
图书类

@Entity
public class Book extends BaseEntity {

private String bookName;
private String bookSubtitle;
private String seriesName;
private String isbnNumber;
private String bookDescription;

@ManyToOne
private Author author;

@ManyToOne
private Publisher publisher;

///// Author class
@Entity
public class Author extends BaseEntity {
     private String authorName;
     private String authorDescription;

     @OneToMany(cascade = CascadeType.ALL, mappedBy = "author", fetch = FetchType.LAZY)
     private Set<Book> books = new HashSet<>();

/////发布者类

@Entity
public class Publisher extends BaseEntity {

private String publisherName;
private String publisherDescription;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "publisher", fetch = FetchType.LAZY)
private Set<Book> books;

protected Publisher() {}

public Publisher(String publisherName, String publisherDescription) {
    this.publisherName = publisherName;
    this.publisherDescription = publisherDescription;
}

//my home.html文件。

<form action="#" th:action="@{/api/v1/books}" th:object="${book}" th:method="POST">
            <div class="form-group col-7">
                <label for="bookName" class="col-form-label">Kitap Adi:</label>
                <input th:field="*{bookName}" type="text" class="form-control" id="bookName">
            </div>
            <div class="form-group col-7">
                <label for="subTitle" class="col-form-label">Alt Baslik:</label>
                <input th:field="*{bookSubtitle}" type="text" class="form-control" id="subTitle">
            </div>
            <div class="form-group col-7">
                <label for="seriesName" class="col-form-label">Seri Adi:</label>
                <input th:field="*{seriesName}" type="text" class="form-control" id="seriesName">
            </div>
            <div class="form-group col-7">
                <label for="isbnNumber" class="col-form-label">ISBN:</label>
                <input th:field="*{isbnNumber}" type="text" class="form-control" id="isbnNumber">
            </div>
            <div class="form-group">
                <label for="bookDescription" class="col-form-label">Kitap Aciklamasi:</label>
                <input th:field="*{bookDescription}" type="text" class="form-control" id="bookDescription">
            </div>

            <div class="form-group">
                <label for="exampleFormControlSelect1">Yazar sec</label>
                <select class="form-control" id="exampleFormControlSelect1" th:field="*{author}">
                    <option th:each="aut : ${authors}" th:value="${(aut.getAuthorName())}" th:text="${aut.getAuthorName()}"></option>
                </select>
            </div>

            <div class="form-group">
                <label for="exampleFormControlSelect2">Yayinci sec</label>
                <select class="form-control" id="exampleFormControlSelect2" th:field="*{publisher}">
                    <option th:each="publish : ${publishers}" th:value="${publish.getPublisherName()}" th:text="${publish.getPublisherName()}"></option>
                </select>
            </div>

            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Iptal</button>
                <button type="submit" class="btn btn-primary">Ekle</button>
            </div>
        </form>

这是我的管理员,正在创建一本书。

@PostMapping("/books")
public Book createBook(Book book) {
    logger.info(book.toString());
    return bookService.save(book);
}

这是我的bookservice save()方法,它完成了所有的工作。我已经从author和publisher中创建了一个对象,并且以我正在循环遍历它们的形式。所以,基本上我的目标是让用户选择作者和出版商的名字以及图书的详细信息,并将它们Map到一起。但是,我尝试了很多东西,做了很多改变,也检查了一下互联网,仍然没有找到解决办法。这些代码段有什么问题?

public Book save(Book book) {

    Set<Book> books = new HashSet<>();
    System.out.println(book.getPublisher().getPublisherName());
    System.out.println(book.getAuthor().getAuthorName());

    String authorName = book.getPublisher().getPublisherName();
    String publisherName = book.getAuthor().getAuthorName();

    Author author = authorRepository.findAuthorByAuthorName(authorName);
    Publisher publisher = publisherRepository.findByPublisherName(publisherName);

    book.setAuthor(author);
    book.setPublisher(publisher);

    books.add(book);

    author.setBooks(books);
    publisher.setBooks(books);

    return bookRepository.save(book);

}
wb1gzix0

wb1gzix01#

最好创建一个专用的“表单数据”对象。在你的例子中,我会:

public class CreateBookFormData {
  private String bookName;
  private String bookSubtitle;
  private String seriesName;
  private String isbnNumber;
  private String bookDescription;

  private UUID authorId; // Use whatever type of primary key you are using here
  private UUID publisherId;
}

控制器将更改为:

@PostMapping("/books")
public Book createBook(CreateBookFormData formData) {
    logger.info(book.toString());
    // You can either pass in the `CreateBookFormData`, or convert it here to a `Book` instance.
    // You will need to convert the `authorId` and `publisherId` to the corresponding entities using their respective repositories or services
    return bookService.save(formData);
}

请注意,不能使用作者或发布者的名称,因为可能存在重复的名称。您需要使用实体的主键。
在thymeleaf模板中,执行以下操作:

<select th:field="*{authorId}">
  <option th:each="author : ${authors}" th:text="${author.authorName}" th:value="${author.id}">
          </select>

对出版商也一样。

相关问题