Сохранение нового или существующего родительского объекта с новым или существующим дочерним объектом - PullRequest
0 голосов
/ 10 января 2020

У меня есть 3 таблицы базы данных (books, authors, books_authors), и они представлены 2 сущностями (Book, Author) с однонаправленным отношением «многие ко многим». Каждый класс сущностей имеет свои Repository (расширяющий JpaRepository) и Service класс.

Цель состоит в том, чтобы иметь возможность сохранить новый или существующий Book с новым или существующим Author ( s) то есть сохранение детей вместе с родителем.

При попытке сохранить новый Book с существующими Author, используя единственный метод сохранения, предоставленный JpaRepository (save), Я получаю исключение о том, что

отдельная сущность передана для сохранения

Поскольку Book является новым, метод save будет использовать persist вместо merge и persist каскадно (из-за CascadeType.PERSIST) к детям, которые уже существуют. Есть ли способ каскадного сохранения разумным способом, когда он использует persist и merge на основе текущего Entity вместо того, что было каскадно от родительского? Я думаю, что это общая проблема, поэтому должно быть хорошо разработанное решение.

Из обсуждений, которые мне удалось найти и понять, удаление CascadeType.PERSIST решило бы проблему с отсоединенной сущностью, но это не дать вам возможность спасти детей вместе с родителем. Кроме того, save можно заменить на merge (требуется использование EntityManager), но это заставит задуматься, зачем вообще беспокоиться о save, и, основываясь на обсуждениях, которые я прочитал, это может не быть решением.


books

идентификатор, имя

authors

идентификатор, имя

books_authors

id, book_id, author_id


@Entity
@Table(name = "books")
public class Book {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(insertable = false, name = "id", nullable = false)
private Long id;

@ManyToMany(
    fetch = FetchType.EAGER,
    cascade = {
        CascadeType.PERSIST,
        CascadeType.MERGE,
        CascadeType.REFRESH,
        CascadeType.DETACH
    })
@JoinTable(
    name = "books_authors",
    joinColumns = @JoinColumn(name = "book_id"),
    inverseJoinColumns = @JoinColumn(name = "author_id"))
private Set < Author > authors;

}

@Entity
@Table(name = "authors")
public class Author {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(insertable = false, name = "id", nullable = false)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;

}
...