Spring 数据 JPA 实体图不适用于 Spring 引导
Spring Data JPA entity graphs are not working with Spring Boot
当应用程序基于 Spring Boot 时,不考虑定义的实体图。相反,在 JUnit 测试期间一切正常。
域非常简单:书籍及其类别(多对多关系)。
书 class:
@Entity
@NamedEntityGraph(name = "Book.summary",
attributeNodes = { @NamedAttributeNode("book_id"), @NamedAttributeNode("title")})
public class Book {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long book_id;
private String title;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "BOOK_CATEGORY",
joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "book_id"),
inverseJoinColumns = @JoinColumn(name = "category_id", referencedColumnName = "category_id"))
private List<Category> categories;
类别class:
@Entity
public class Category {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long category_id;
private String name;
@ManyToMany(mappedBy = "categories")
private List<Book> books;
具有使用创建的实体图的方法的 JPA 存储库:
@Component
@Repository
public interface BookJpaRepository extends JpaRepository<Book, Long> {
@Override
@EntityGraph(value = "Book.summary", type = EntityGraph.EntityGraphType.FETCH)
List<Book> findAll(); }
在 REST 控制器中的用法:
@RequestMapping("/books")
@ResponseBody
public List<Book> getBooksSummary() {
return bookJpaRepository.findAll();
}
启动后 Spring Boot (mvn spring-boot:运行) 并导航到 http://localhost:8080/books 书籍显示,但有各自的类别(例外是由于无限递归而抛出:书籍 -> 类别 -> 书籍 -> 类别 -> ...)。
测试中的相同代码(运行 与 SpringJUnit4ClassRunner)按预期工作并且实体图被正确识别。例如,下面的代码没有显示类别,因为正如预期的那样有延迟初始化:
@Test
public void testEntityGraph() {
List<Book> all = bookJpaRepository.findAll();
System.out.println(all.get(0).getCategories());
}
关于如何在应用程序 运行 在 Spring 启动时使实体图工作的任何建议?
正如 Rae Burawes(谢谢!)在评论中指出的那样,这种行为的原因是序列化。
为了处理 Jackson 序列化程序获取的数据,我们可以使用这些注释:
- com.fasterxml.jackson.annotation.JsonIdentityInfo
- 在 class/field
- com.fasterxml.jackson.annotation.JsonManagedReference
或 com.fasterxml.jackson.annotation.JsonIgnore
- 场上
可以在 this tutorial 中找到更多信息。
当应用程序基于 Spring Boot 时,不考虑定义的实体图。相反,在 JUnit 测试期间一切正常。
域非常简单:书籍及其类别(多对多关系)。
书 class:
@Entity
@NamedEntityGraph(name = "Book.summary",
attributeNodes = { @NamedAttributeNode("book_id"), @NamedAttributeNode("title")})
public class Book {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long book_id;
private String title;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "BOOK_CATEGORY",
joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "book_id"),
inverseJoinColumns = @JoinColumn(name = "category_id", referencedColumnName = "category_id"))
private List<Category> categories;
类别class:
@Entity
public class Category {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long category_id;
private String name;
@ManyToMany(mappedBy = "categories")
private List<Book> books;
具有使用创建的实体图的方法的 JPA 存储库:
@Component
@Repository
public interface BookJpaRepository extends JpaRepository<Book, Long> {
@Override
@EntityGraph(value = "Book.summary", type = EntityGraph.EntityGraphType.FETCH)
List<Book> findAll(); }
在 REST 控制器中的用法:
@RequestMapping("/books")
@ResponseBody
public List<Book> getBooksSummary() {
return bookJpaRepository.findAll();
}
启动后 Spring Boot (mvn spring-boot:运行) 并导航到 http://localhost:8080/books 书籍显示,但有各自的类别(例外是由于无限递归而抛出:书籍 -> 类别 -> 书籍 -> 类别 -> ...)。
测试中的相同代码(运行 与 SpringJUnit4ClassRunner)按预期工作并且实体图被正确识别。例如,下面的代码没有显示类别,因为正如预期的那样有延迟初始化:
@Test
public void testEntityGraph() {
List<Book> all = bookJpaRepository.findAll();
System.out.println(all.get(0).getCategories());
}
关于如何在应用程序 运行 在 Spring 启动时使实体图工作的任何建议?
正如 Rae Burawes(谢谢!)在评论中指出的那样,这种行为的原因是序列化。
为了处理 Jackson 序列化程序获取的数据,我们可以使用这些注释:
- com.fasterxml.jackson.annotation.JsonIdentityInfo
- 在 class/field
- com.fasterxml.jackson.annotation.JsonManagedReference
或 com.fasterxml.jackson.annotation.JsonIgnore
- 场上
可以在 this tutorial 中找到更多信息。