Java spring数据jpa多对多findByID
我有书和作者之间的多对多关系,我有三个表:作者、书和作者书Java spring数据jpa多对多findByID,java,spring-boot,spring-data-jpa,many-to-many,Java,Spring Boot,Spring Data Jpa,Many To Many,我有书和作者之间的多对多关系,我有三个表:作者、书和作者书 @Entity() @Table(name = "author") public class Author implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; @ManyToMany(casca
@Entity()
@Table(name = "author")
public class Author implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(
name = "author_book",
joinColumns = @JoinColumn(name = "author_id"),
inverseJoinColumns = @JoinColumn(name = "book_id")
)
private List<Book> authorBooks = new ArrayList<Book>();
public Author() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Book> getAuthorBooks() {
return authorBooks;
}
public void setAuthorBooks(List<Book> authorBooks) {
this.authorBooks = authorBooks;
}
@Override
public String toString() {
return "Author{" + "name=" + name + ", authorBooks=" + authorBooks + '}';
}
}
@Entity()
@Table(name = "book")
public class Book implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToMany(mappedBy = "authorBooks", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Author> bookAuthors = new ArrayList<Author>();
public Book() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Author> getBookAuthors() {
return bookAuthors;
}
public void setBookAuthors(List<Author> bookAuthors) {
this.bookAuthors = bookAuthors;
}
@Override
public String toString() {
return "Book{" + "name=" + name + ", bookAuthors=" + bookAuthors + '}';
}
}
@Entity()
@表(name=“author”)
公共类Author实现了可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
私有字符串名称;
@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@可接合(
name=“author\u book”,
joinColumns=@JoinColumn(name=“author\u id”),
inverseJoinColumns=@JoinColumn(name=“book\u id”)
)
私有列表authorBooks=new ArrayList();
公共作者(){
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共列表getAuthorBooks(){
返回authorBooks;
}
public void setAuthorBooks(列出authorBooks){
this.authorBooks=authorBooks;
}
@凌驾
公共字符串toString(){
返回“Author{“+”name=“+name+”,authorBooks=“+authorBooks+'}”;
}
}
@实体()
@表(name=“book”)
公共类图书实现了可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
私有字符串名称;
@ManyToMany(mappedBy=“authorBooks”,cascade=CascadeType.ALL,fetch=FetchType.LAZY)
private List bookAuthors=new ArrayList();
公共书籍(){
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共列表getBookAuthors(){
返回图书作者;
}
公共书籍作者(列出书籍作者){
this.bookAuthors=bookAuthors;
}
@凌驾
公共字符串toString(){
返回“Book{”+“name=“+name+”,bookAuthors=“+bookAuthors+”}”;
}
}
我可以毫无问题地将数据添加到db中,但是当我想通过id获取作者或书籍时
Optional<Author> optionalAuthor = authorReposi.findById(1L);
System.out.println("Author: " + optionalAuthor.get().toString());
可选选项author=authorReposi.findById(1L);
System.out.println(“作者:+optionalAuthor.get().toString());
我收到一个错误:懒散初始化失败…
我想使用FetchType.LAZY并获取author或book的实例
谢谢您的时间。所以,请阅读精美手册:
您的问题很简单,您的toString()
方法是递归的<代码>作者表示打印书籍
,书籍
表示打印作者
。专业提示:成功在于细节
对于load
或fetch
,您需要使用JPA
中的EntityGraph
来指定连接的属性。因此:
@Entity()
@Table(name = "author")
@NamedEntityGraph(name = "Book.detail", attributeNodes = @NamedAttributeNode("books"))
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToMany
private List<Book> books;
}
最后,我避免像瘟疫一样使用Cascade
注释。它们是复杂的注释。另外,默认情况下,manytomy
是FetchType.LAZY
。重要的注释是mappedBy
注释。这将告诉您哪个实体拥有关系。拥有实体是负责维持关系的实体。双向注释的另一面实际上只用于查询。不需要在实体中创建新的ArrayList
,因为它们在查询过程中会被丢弃。当需要持久化具有关系的新作者
实体时,只需创建一个列表,否则使用查询返回的列表
private Author save() {
Book b = bookRepository.save(Book.builder().name("b1").build());
return authorRepository.save(Author.builder().name("a1").books(Collections.singletonList(b)).build());
}
这可能有助于您始终不一致地使用
author
和auhtor
。正确的拼写是author
。我建议重命名所有内容以与此对齐,然后看看会发生什么。@Jason我修复了作者的拼写,仍然有相同的问题。谢谢你们。谢谢你们的解释,它正在工作。我将使用EntityGraph。是否可以执行此调用:author.getBooks().get(0).getAuthors()我必须添加cascade=CascadeType.ALL才能将新的author添加到db中。1)我认为这是可能的,但您必须尝试。查看实体图的子图。2) 我将一个新作者保存到数据库中,如上所示。也许你将CASCADE添加到Books实体中是为了从那里拯救作者,但我个人不建议这样做。我认为最好保持JPA注释的基础性,并根据需要创建一个处理各种不同情况的服务层。
public interface AuthorRepository extends JpaRepository<Author, Long>{
@EntityGraph(value = "Book.detail", type = EntityGraphType.LOAD)
Author getById(Long id);
}
public interface BookRepository extends JpaRepository<Book, Long>{
}
private void read(Long id) {
Author a = authorRepository.getById(id);
System.out.println("Author: " + a.getName());
for( Book b: a.getBooks()) {
System.out.println("\tBook: " + b.getName());
}
}
private Author save() {
Book b = bookRepository.save(Book.builder().name("b1").build());
return authorRepository.save(Author.builder().name("a1").books(Collections.singletonList(b)).build());
}