我有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
引发错误。
错误
使用用例“作者表中存在一个作者,而作者表中不存在另一个作者”,这是基于CascadeType
的错误:
CascadeType.all
=> org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist
,这是因为持久保留作者只有在没有id的情况下才是成功的,因为author的ID用@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
,这是因为我有一个包含一个或多个数据库中不存在的项目的集合({{1} }表)。那么,实现它的正确方法是什么?
答案 0 :(得分:0)
我会这样尝试:
for (AuthorDto authorDto : dataAuthorDto) {
Author author = authorDao.findByName(authorDto.getName());
if (null == author) {
author = new Author();
BeanUtils.copyProperties(authorDto, author);
}
dataAuthor.add(author);
}
这样,如果您在数据库中找到一位作者,则将现有的作者与您的书一起引用,而不用创建新的作者。这样,您就不会在持久性上下文中得到两个相同的作者(一个是使用findByName找到的,另一个是您创建并被您的书引用的)。我没有测试此解决方案,如果无法解决,请在评论中告知我。