Избегайте добавления одних и тех же данных с отношениями многие ко многим jpa - PullRequest
0 голосов
/ 02 июля 2019

У меня есть сценарий, книга может иметь одну категорию и принадлежать множеству авторов. В категории может быть много книг. Автору может принадлежать много книг.

Итак,

  1. Book до BookCategory - это many-to-one
  2. Book до Author и Author до Book - это many-to-many (в таблице book_author)
  3. BookCategory до Book - это one-to-many

Я мог бы сохранить (с кодом ниже) новую книгу с автором, а также с категорией. Но проблема в следующем:

  1. Если я не проверял, существует ли автор в таблице Author, тот же автор будет снова вставлен в Author таблицу
  2. Если я проверю, существует ли уже тот же автор в таблице Author, а затем исключить автора из списка, как таблица book_author узнает, если книга имеет связь с уже существующим автором?

Вот как я объявляю сущность и сервис:

BookDto

public class BookDto {
    private String title;
    private String year;
    private Set<AuthorDto> author;
    private String category;
}

AuthorDto

public class AuthorDto {
    private String name;
    private String address;
}

Книга

@Entity(name = "book")
@Table(name = "book", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "title", nullable = false)
    private String title;
    @Column(name = "year", nullable = false)
    private String year;
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
      name = "book_author",
      joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "id"),
      inverseJoinColumns = @JoinColumn(name = "author_id", referencedColumnName = "id"))
    @JsonManagedReference
    private Set<Author> author;
    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id", referencedColumnName = "id", nullable = false)
    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) 
    private BookCategory category;
}

Автор

@Entity(name = "author")
@Table(name = "author", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "name", nullable = false)
    private String name;
    @Column(name = "address", nullable = false)
    private String address;
    @ManyToMany(mappedBy = "author", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JsonBackReference
    private Set<Book> book;
}

BookCategory

@Entity(name = "book_category")
@Table(name = "book_category")
public class BookCategory {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "category", nullable = false)
    private String category;
}

BookServiceImpl

public class BookServiceImpl implements BookService {
    public BookDto save(BookDto bookDto) throws Exception {
        try {
            Book book = new Book();
            BeanUtils.copyProperties(bookDto, book, "author", "category");
            BookCategory bookCategory = bookCategoryDao.findByCategory(bookDto.getCategory());

            Set<Author> dataAuthor = new HashSet<Author>();
            Set<AuthorDto> dataAuthorDto = new HashSet<AuthorDto>();
            bookDto.getAuthor().iterator().forEachRemaining(dataAuthorDto::add);

            for (AuthorDto authorDto : dataAuthorDto) {
                Author author = new Author();
                /** 
                 * Problem is:
                 * 1. If I did not check whether the author already exist in
                 * Author table, the same author will inserted again into Author table
                 * 2. If I check whether same author already exist in Author table, then omit
                 * the author from the list, how book_author table would know if
                 * the book have relationship with already existed author?
                 * */
                BeanUtils.copyProperties(authorDto, author);
                dataAuthor.add(author);
            }

            book.setAuthor(dataAuthor);
            book.setCategory(bookCategory);
            bookDao.save(book);
        } catch (Exception e) {
            throw new Exception(e);
        }
        return null;
    }
}

Любая помощь будет очень полезна. Спасибо!

1 Ответ

0 голосов
/ 02 июля 2019

Если я не проверял, существует ли уже автор в таблице Автор, тот же автор будет снова вставлен в таблицу Автор

Исправить.Это приводит к заключению, что если вы не хотите дубликатов, вы должны проверить, существует ли автор, каким бы ни было ваше определение «того же» автора.

Если я проверю, существует ли уже тот же автор в таблице Автор, а затем исключить автора из списка, как таблица book_author узнает, если книга имеет связь с уже существующим автором?

Ну, тогда не опускайте это.Посмотри вместо этого.Предполагая, что вы определяете одного и того же автора как «автора с тем же именем», просто добавьте следующий метод к DataAuthorRepository (или как вы его назвали):

Optional<Author> findByNameIgnoreCase(String name)

И затем, в BookServiceImpl, просто сделайте следующее:

for (AuthorDto authorDto : dataAuthorDto) {
    Author author = dataAuthor.findByNameIgnoreCase(authorDto.getName())
    .orElseGet(() -> {
        Author newAuthor = new Author();
        BeanUtils.copyProperties(authorDto, newAuthor);
        return newAuthor;
    });
    dataAuthor.add(author);
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...