Объединение трех таблиц с ассоциацией @ManyToMany - PullRequest
0 голосов
/ 12 февраля 2019

Объединение трех таблиц с ассоциацией @ManyToMany

Я реализую приложение Book Store, используя Spring Boot и Spring Data JPA.Я пробовал это с ассоциациями @onetoone, @manytoone и @onetomany, но я застрял в ассоциации @ManyToMany.

Существует три таблицы - Книга, Жанр и Автор.Я хочу сделать следующее 1) Создать новую таблицу - Book_Genre_Author 2) Если Автор или Жанр уже существует в базе данных, он не делает новую запись в базе данных.3) Если Book уже существует в базе данных, она не делает запись в базе данных.4) Как реализовать операции вставки и обновления с использованием Spring Data JPA?

Вот мои три сущности -

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

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CUSTOM_SEQUENCE")
@SequenceGenerator(sequenceName = "customer_seq", allocationSize = 1, name = "CUSTOM_SEQUENCE")
@Column(name = "BookId")
int bookId;

public int getBookId() {
    return bookId;
}

public void setBookId(int bookId) {
    this.bookId = bookId;
}

@Column(name = "BookName")
String bookName;



@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "Book_Author_Genre", joinColumns = @JoinColumn(name = "bookId"), inverseJoinColumns = @JoinColumn(name = "genreId"))
@MapKeyJoinColumn(name = "authorId")
@ElementCollection
private Map<Author, Genre> authorGenre = new HashMap<>();

public Map<Author, Genre> getAuthorGenre() {
    return authorGenre;
}

public void setAuthorGenre(Map<Author, Genre> authorGenre) {
    this.authorGenre = authorGenre;
}

@Column(name = "Language")
String language;



@Column(name = "GoodReadReviews")
String goodReadReviews;


  @Override public String toString() { return "BookId=" + this.bookId +
  "::BookName=" + this.bookName + "::AuthorId=" + "Will check how to get it" +
  "::Langauge = " + this.language + "::GenreId = " + "Will check how to get it" +
  "::GoodReadReviews=" + this.goodReadReviews;

  }


public String getBookName() {
    return bookName;
}

public void setBookName(String bookName) {
    this.bookName = bookName;
}

public String getLanguage() {
    return language;
}

public void setLanguage(String language) {
    this.language = language;
}

public String getGoodReadReviews() {
    return goodReadReviews;
}

public void setGoodReadReviews(String goodReadReviews) {
    this.goodReadReviews = goodReadReviews;
}

}

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

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="AuthorSeqGenerator")
@SequenceGenerator(sequenceName = "author_seq", allocationSize = 1, name = "AuthorSeqGenerator")
@Column(name="AuthorId")
int authorId;

@Column(name="AuthorName")
String authorName;

@Column(name="Country")
String country;

@Column(name="Gender")
String gender;


public int getAuthorId() {
    return authorId;
}
public void setAuthorId(int authorId) {
    this.authorId = authorId;
}


public String getAuthorName() {
    return authorName;
}
public void setAuthorName(String authorName) {
    this.authorName = authorName;
}
public String getCountry() {
    return country;
}
public void setCountry(String country) {
    this.country = country;
}
public String getGender() {
    return gender;
}
public void setGender(String gender) {
    this.gender = gender;
}

}

@Entity
@Table(name="Genre_details")
public class Genre {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="GenreSeqGenerator")
@SequenceGenerator(sequenceName = "genre_seq", allocationSize = 1, name = "GenreSeqGenerator")
int genreId;

@Column(name="GenreName")
String genreName;

public int getGenreId() {
    return genreId;
}

public void setGenreId(int genreId) {
    this.genreId = genreId;
}




public String getGenreName() {
    return genreName;
}

public void setGenreName(String genreName) {
    this.genreName = genreName;
}

}

Я пытался сохранить детали книги, используя следующий код -

Author author = new Author();
        author.setAuthorName("Rabindranath Tagore");
        author.setCountry("India");
        author.setGender("Male");

    Genre genre = new Genre();
    genre.setGenreName("Fiction");

    Book book = new Book();
    book.setBookName("Gitanjali");
    book.setGoodReadReviews("5");
    book.setLanguage("Bengali");
    HashMap<Author,Genre> authorGenre = new HashMap<>();
    authorGenre.put(author, genre);
    book.setAuthorGenre(authorGenre);

    bookRepository.save(book);

Но я получаю сообщение об ошибке ниже.

Вызывается: org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом: com.bsm.app.model.Author;вложенным исключением является java.lang.IllegalStateException: org.hibernate.TransientObjectException: объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом: com.bsm.app.model.Author

Я могу ошибаться в своем подходе, поскольку я наивен в этом.Пожалуйста, предлагайте и поддержите.

1 Ответ

0 голосов
/ 12 февраля 2019

Я бы предложил создать новую связующую сущность, которая будет использоваться для отображения этой конкретной таблицы.

Вам просто нужно решить, остаться ли с составным первичным ключом или добавить искусственный идентификатор (рекомендуется).

Похоже, что эта установка требует больше кодирования, но из моего опыта становится более ясным, когда в игру вступят 3 стола:

class Book {
    @OneToMany(mappedBy = "book", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Set<BookAuthorGenreLink> bookAuthorGenreLinks;
}

class Author{
    @OneToMany(mappedBy = "author", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Set<BookAuthorGenreLink> bookAuthorGenreLinks;
}

class Genre{
    @OneToMany(mappedBy = "genre", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Set<BookAuthorGenreLink> bookAuthorGenreLinks;
}

Таблица связывания:

class BookAuthorGenreLink {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "book_id")
    private Book book;

    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "author_id")
    private Author author;

    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "genre_id")
    private Genre genre;

}
...