gpt4 book ai didi

java - 使用数据库jpa中现有和不存在的数据持久保存新数据时出错

转载 作者:行者123 更新时间:2023-12-02 03:36:34 25 4
gpt4 key购买 nike

我有 Book 表和 Author 表。他们的关系是多对多

我的目标

我希望能够坚持新书。如果书籍的作者已存在于 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 的错误:

  1. 如果我使用CascadeType.all => org.springframework.dao.InvalidDataAccessApiUsageException:分离的实体传递给持久化,因为持久化作者只有在以下情况下才会成功没有 id,因为作者的 id 是用 @GenerateValue(strategy = GenerationType.IDENTITY) 注释的。
  2. 如果我删除 CascadeType 或使用 CascadeType.MERGE => org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: 对象引用未保存的 transient 实例 - 在刷新之前保存 transient 实例,这是因为我有一个集合,其中包含数据库(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 找到的作者,以及您在书籍中创建和引用的作者)。我没有测试这个解决方案,如果它不起作用,请在评论中告诉我。

关于java - 使用数据库jpa中现有和不存在的数据持久保存新数据时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56856048/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com