У меня есть Book
таблица и Author
таблица.Их отношения many-to-many
.
Моя цель
Я хочу сохранить новую книгу.Если автор книги уже существует в таблице Author
, я не хочу сохранять этого автора в таблице Author
.Если автора нет в таблице Author
, данные об авторе будут сохранены в таблице Author
.Вот как я объявляю сущность и serviceImplementation для сохранения данных:
Книга
@Entity(name = "book")
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")
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;
}
BookServiceImpl
public class BookServiceImpl implements BookService {
@Override
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();
Author author_ = authorDao.findByName(authorDto.getName());
if (null == author_) {
BeanUtils.copyProperties(authorDto, author);
} else {
BeanUtils.copyProperties(author_, author);
}
dataAuthor.add(author);
}
book.setAuthor(dataAuthor);
book.setCategory(bookCategory);
bookDao.save(book);
} catch (Exception e) {
e.printStackTrace();
throw new Exception(e);
}
return null;
}
}
Вот пример ввода json, когда я делаю запрос:
{
"title": "book1",
"year": "2013",
"author": [
{
"name": "angel",
"address": "NY"
}, {
"name": "john",
"address": "LA"
}
],
"category": "science"
}
Над кодом работает, если все авторы либосуществует в Author
таблице или не существует вообще в Author
таблице.Если один из них существует, а другой не существует, он выдаст ошибку, основанную на CascadeType
, который я использовал при определении сущности.
Ошибка
Использование useВ случае «один автор существует в таблице Автор, а другой не существует в таблице Автор», здесь приведена ошибка, основанная на CascadeType
:
- Если я использую
CascadeType.all
=> org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist
Это потому, что сохранение автора имеет успех только в том случае, если у него нет идентификатора, потому что идентификатор автора помечается @GeneratedValue(strategy = GenerationType.IDENTITY)
. - Если я удаляю
CascadeType
или использую CascadeType.MERGE
=> org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing
, чтопотому что у меня есть коллекция, в которой есть один или несколько элементов, которых нет в базе данных (Author
таблица).
Итак, как правильно достичь этого?