我在书和作者之间有很多关系,我有三个表:作者,书和author_book。
@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 + '}';
}
}我可以将数据添加到db中,而不存在任何问题,但是当我想通过id获得作者或书籍时,我可以将数据添加到数据库中。
Optional<Author> optionalAuthor = authorReposi.findById(1L);
System.out.println("Author: " + optionalAuthor.get().toString());我犯了一个错误:LazyInitialization懒惰地失败了.
我想使用FetchType.LAZY并获得作者或书籍的实例。
谢谢您抽时间见我。
发布于 2021-01-13 02:12:50
因此,请阅读详细的手册:6.3.10。配置Fetch和LoadGraphs。
您的问题只是您的toString()方法是递归的。Authors说打印Books,Books说打印Authors。小贴士:成功在于细节。
对于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;
}和
@Entity()
@Table(name = "book")
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToMany(mappedBy = "books")
private List<Author> authors;
}拥有存储库:
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>{
}那你必须自己打印出你想要的。基本上,将toStrings放在Entities中通常会导致问题,但您也应该使用RTFM。
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());
}
}最后,我避免使用像瘟疫这样的Cascade注释。它们是复杂的注释。而且,默认情况下,ManyToMany是FetchType.LAZY。重要的注释是mappedBy注释。这将告诉您是哪个实体拥有这种关系。拥有的实体是负责维持关系的实体。双向注释的另一面实际上只适用于查询。没有必要在实体中创建新的ArrayList,因为在查询期间它们将被丢弃。当您需要持久化带有关系的新Author实体时,只需创建一个列表,否则使用查询返回的列表。
private Author save() {
Book b = bookRepository.save(Book.builder().name("b1").build());
return authorRepository.save(Author.builder().name("a1").books(Collections.singletonList(b)).build());
}https://stackoverflow.com/questions/65693017
复制相似问题