java - 使用数据库 jpa 中现有和不存在的数据保留新数据时出错
问题描述
我有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 的情况下才成功,因为作者的 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
,这是因为我有一个集合,其中包含一个或多个数据库(Author
表)中不存在的项目。
那么,实现它的正确方法是什么?
解决方案
我会这样尝试:
for (AuthorDto authorDto : dataAuthorDto) {
Author author = authorDao.findByName(authorDto.getName());
if (null == author) {
author = new Author();
BeanUtils.copyProperties(authorDto, author);
}
dataAuthor.add(author);
}
这样,如果您在数据库中找到一位作者,您将在您的书中引用现有作者,而不是创建一个新作者。这样,您就不会在持久性上下文中找到两个相同的作者(一个是您使用 findByName 找到的,另一个是您创建并在您的书中引用的)。我没有测试这个解决方案,如果它不起作用,请在评论中告诉我。
推荐阅读
- flutter - 零安全飞镖
- java - 初始化有界泛型 Java
- ios - 离子构建报告在配置文件中缺少“关联域”权利,当它已经存在时
- python-3.x - 如何在用户输入 url 一段时间后运行函数?姜戈
- python - 如何将pycharm终端输出重定向到tkinter GUI窗口
- python-3.x - 为什么 Visual Studio Code 函数颜色之间存在差异?
- python - 如何使用自定义按钮修改 Plotly 图形的布局
- multithreading - 引起:java.sql.SQLException:TDengine 错误:无效的结果集指针
- functional-programming - 使用函数创建结构实例
- reactjs - 无法加载配置“react-app”以从