Defined entity graph is not taken into consideration when application is based on Spring Boot. In contrary, everything works fine during JUnit tests.
Domain is quite simple: books and their categories (many to many relation).
Book 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;
Category 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 repository with method that uses created entity graph:
@Component
@Repository
public interface BookJpaRepository extends JpaRepository<Book, Long> {
@Override
@EntityGraph(value = "Book.summary", type = EntityGraph.EntityGraphType.FETCH)
List<Book> findAll(); }
Usage in REST controller:
@RequestMapping("/books")
@ResponseBody
public List<Book> getBooksSummary() {
return bookJpaRepository.findAll();
}
After starting Spring Boot (mvn spring-boot:run) and navigating to http://localhost:8080/books books are displayed, but with their respective categories (and exception is thrown because of infinite recursion: books -> categories -> books -> categories -> ...).
The same code in test (run with SpringJUnit4ClassRunner) is working as expected and entity graph is correctly recognized. For example, code below is not displaying the categories because as expected there is lazy initialization:
@Test
public void testEntityGraph() {
List<Book> all = bookJpaRepository.findAll();
System.out.println(all.get(0).getCategories());
}
Any suggestions how to get entity graphs working when application is running on Spring Boot?
As pointed by Rae Burawes (thanks!) in comments, reason for this behaviour was serialization.
To handle fetching of data by Jackson serializer we can use these annotations:
- com.fasterxml.jackson.annotation.JsonIdentityInfo
- on class/field
- com.fasterxml.jackson.annotation.JsonManagedReference
or com.fasterxml.jackson.annotation.JsonIgnore
- on field
More information can be found in this tutorial.