Графики сущностей Spring Data JPA не работают с Spring Boot

Определенный граф объектов не принимается во внимание, когда приложение основано на Spring Boot. Напротив, во время тестов JUnit все работает нормально.

Домен довольно прост: книги и их категории (отношение «многие ко многим»).
Класс книги:

@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;

Класс категории:

@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:run) и перехода к http://localhost:8080/books книгам отображаются, но с соответствующими категориями (и возникает исключение из-за бесконечной рекурсии: книги -> категории -> книги -> категории -> ...).

Тот же код в тесте (запущенный с помощью SpringJUnit4ClassRunner) работает, как и ожидалось, и граф объектов распознается правильно. Например, приведенный ниже код не отображает категории, потому что, как и ожидалось, инициализация отложена:

@Test
public void testEntityGraph() {
    List<Book> all = bookJpaRepository.findAll();

    System.out.println(all.get(0).getCategories());
}

Любые предложения, как заставить графы сущностей работать, когда приложение работает в Spring Boot?


person Marek J    schedule 28.07.2016    source источник
comment
Итак, в чем вопрос? Вот документ NamedEntityGraph, docs.oracle. com/javaee/7/учебник/   -  person Demon Coldmist    schedule 29.07.2016
comment
Вопрос в том, как заставить графы сущностей работать и почему приложение в Spring Boot их игнорирует.   -  person Marek J    schedule 29.07.2016
comment
Я думаю, это может быть полезно: stackoverflow.com/questions /26291143/   -  person Tom Van Rossom    schedule 29.07.2016
comment
Любой вызов геттера коллекции с LAZY fetchType приведет к ее загрузке. Я считаю, что когда вы вызываете метод findAll на своем контроллере, он получает всю сущность, включая свойства, помеченные как LAZY. Именно сериализация вызывает загрузку categories.   -  person Rae Burawes    schedule 29.07.2016


Ответы (1)


Как указал Рэй Буравес (спасибо!) в комментариях, причиной такого поведения была сериализация.
Чтобы обрабатывать выборку данных сериализатором Джексона, мы можем использовать следующие аннотации:
- com.fasterxml.jackson.annotation.JsonIdentityInfo - в классе/поле
- com.fasterxml.jackson.annotation.JsonManagedReference или com.fasterxml.jackson.annotation.JsonIgnore - на поле

Дополнительную информацию можно найти в этом руководстве.

person Marek J    schedule 29.07.2016
comment
Можете ли вы опубликовать свое решение с этими аннотациями? - person Anand Sunderraman; 05.11.2017