Использование Spring Data JPA - как сохранить ТОЛЬКО УНИКАЛЬНЫЕ элементы в дочерней сущности при сохранении родительской сущности и с помощью CascadeType = PERSIST - PullRequest
0 голосов
/ 18 января 2019

Я готовлю простое приложение Spring. У меня есть 2 лица: Book.class (родительский) и Author.class (дочерний): с @OneToMany из представления «Автор» и @ManyToOne (cascade = CascadeType.PERSIST) из отношений представления «Книга». При сохранении новой книги - также автор сохраняется и добавляется в БД (mySql) - что я и хочу. Но я не могу понять, почему Spring добавляет Author - если такой элемент уже существует. Как изменить код, чтобы убедиться, что только уникальные Авторы будут добавлены в БД и будет без дубликатов в таблице авторов в БД ?

Я добавил hashCode и методы equals в класс Author, но это не помогло. Я пытался изменить также Cascade.Type, но также не помог.

Автор.класс (часть кода):

@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";
    }

Был бы признателен за любую подсказку, так как я новичок в этой области: -)

1 Ответ

0 голосов
/ 19 января 2019
  1. Позвольте мне предложить, чтобы ваш Author объект в Book имел пустое поле первичного ключа? Логика Hibernate в этом случае: пустой идентификатор означает новую строку для вставки. Это может работать правильно, если вы установите первичный ключ для автора. Например, пользователь может найти автора (с его PK) или добавить новый (без PK) и вызвать метод save (book), который будет каскадно сохранять только нового автора. В большинстве случаев это обычно работает так.
  2. Еще один момент, на который следует обратить внимание: если вы хотите сохранить уникальность автора в базе данных, вы должны наложить ограничения на сущность автора. Например, если у каждого автора должно быть уникальное имя и фамилия, это может выглядеть примерно так:

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

    После этого DataIntegrityViolationException будет выдано при вставке дублирующего значения, и ваша база данных останется чистой от дубликатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...