0

我正在准备简单的 Spring 应用程序。我有 2 个实体:Book.class(父)和 Author.class(子):来自 Author 视图的 @OneToMany 和来自 Book 视图关系的 @ManyToOne(cascade=CascadeType.PERSIST)。在保存新书的同时——作者也被保存并添加到数据库(mySql)中——这就是我想要的。但我不明白为什么 Spring 添加作者 - 如果这样的项目已经存在。如何更改代码以确保只有唯一的作者将添加到数据库中,并且数据库中的作者表中不会有重复

我已经向 Author 类添加了 hashCode 和 equals 方法,但它没有帮助。我也尝试更改 Cascade.Type 但也没有帮助。

Author.class(部分代码):

@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
@OneToMany(mappedBy = "author")
@JsonManagedReference(value = "book-author")
private Set<Book> books = new HashSet<Book>();
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Author author = (Author) o;
    return Objects.equals(getFirstName(), author.getFirstName()) &&
            Objects.equals(getLastName(), author.getLastName());
    }

    @Override
    public int hashCode() {
    return Objects.hash(getFirstName(), getLastName());
    }

和 Book.class(部分代码):

@Entity
public class Book {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String title;

@ManyToOne( cascade=CascadeType.PERSIST)
@JoinColumn(name = "author_id", unique = true)
@JsonBackReference(value="book-author")
private Author author;

编辑 1 BookServiceImpl.class

@Override
 public BookDto addBookDto(BookDto bookDto) {
    Book book = bookConverter.apply(bookDto);
    bookRepository.save(book);
    return bookDtoConverter.apply(book);
}

AuthorServiceImpl.class

@Override
 public Author findAuthor(String firstName, String lastName) {
    Optional<Author> authorByNameOptional =      authorRepository.findByFirstNameAndLastName(firstName, lastName);
    if (authorByNameOptional.isPresent()) {

        return authorByNameOptional.get();
    } else {
        Author newAuthor = new Author();
        newAuthor.setFirstName(firstName);
        newAuthor.setLastName(lastName);
        return newAuthor;
    }

和 BookWebController.class

@PostMapping("/addWebBook")
    public String addBook(@ModelAttribute(name = "addedBook") BookDto addedBook, Model model) {
        Author author1 = addedBook.getAuthor();
        Author author = authorService.findAuthor(author1.getFirstName(), author1.getLastName());
        addedBook.setAuthor(author);
        bookService.addBookDto(addedBook);
        return "redirect:/message?msg";
    }

任何提示都会非常有用,因为我对这个领域很陌生:-)

4

1 回答 1

3
  1. 让我建议您的Author对象Book具有空的主键字段?Hibernate 在这种情况下的逻辑:空 id 表示要插入新行。如果您将主键设置为作者,它可能会正常工作。例如,用户可以找到作者(使用它的 PK)或添加新的(没有 PK)并调用 save(book) 方法,该方法将级联仅保留新作者。在大多数情况下,通常会这样工作。
  2. 另一个需要注意的时刻,如果你想在数据库中保持作者的唯一性,那么你必须对作者的实体施加约束。例如,如果每个作者必须有唯一的名字和姓氏,它可能看起来像这样:

    @Entity
    @Table(uniqueConstraints= @UniqueConstraint(columnNames={"first_name", "last_name"}))
    public class Author {
    ...
    

    之后,DataIntegrityViolationException将在重复值插入时抛出,并且您的数据库将保持干净的重复。

于 2019-01-19T08:00:47.923 回答