Как решить Lazy инициализировать Исключение, чтобы получить список данных, используя Hibernate Двунаправленное сопоставление один ко многим - PullRequest
0 голосов
/ 15 ноября 2018

Рассмотрим следующие две таблицы - сообщения и комментарии схемы базы данных блога, в которой таблица сообщений имеет отношение один ко многим с таблицей комментариев.

Я использую Двунаправленная связь Один ко многимОтображение , потому что мои дочерние объекты ограничены только.

В Двунаправленное отображение один-ко-многим , я написал один вызов rest, чтобы получить все сообщения с соответствующими комментариями для сообщения Использование по умолчаниюнайти все методы в репозитории JPA.

Но произошло следующее исключение:

"message": "Could not write JSON: failed to lazily initialize a collection of role: com.insights.apartmento.modal.Post.comments, could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.insights.apartmento.modal.Post.comments, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.insights.apartmento.modal.Post[\"comments\"])",

Мой класс Pojo выглядит следующим образом

In POST POJO
@Entity
@Table(name = "posts")
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Size(max = 100)
    @Column(unique = true)
    private String title;

    @Size(max = 250)
    private String description;

    @Lob
    private String content;

    @OneToMany(cascade = CascadeType.ALL,
            fetch = FetchType.LAZY,
            mappedBy = "post")
    private Set<Comment> comments = new HashSet<>();

    // Getters and Setters (Omitted for brevity)
}

В комментариях POJO

@Entity
@Table(name = "comments")
public class Comment{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Lob
    private String text;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id", nullable = false)
    private Post post;

    // Getters and Setters (Omitted for brevity)
}

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

Вы пытаетесь сериализовать непосредственно объект Post.Происходит то, что маршаллер Джексона пытается построить JSON из полного класса, включая private Set<Comment> comments

Поскольку вы используете Lazy FetchType (правильно, по мне), Hibernate выдаст LazyInitializationException Вы можете избежатьэто можно сделать несколькими способами:

  1. Вы можете игнорировать набор comments в сгенерированном JSON, используя аннотацию @JsonIgnore для этого свойства
  2. Вы можете полностью загрузить объект Post, ноиспользуя другой FetchType (например, EAGER или JOIN)
  3. Вы можете использовать метод Hibernate.initialize

Какое решение использовать?Ну, это зависит от вашего варианта использования.В любом случае я настоятельно рекомендую вам избегать решения № 2 (полностью загрузить объект Post, но использовать другой FetchType (например, EAGER или JOIN), потому что это означает, что вы всегда будете загружать сообщения со всеми комментариями, и этоочень влияет на производительность

0 голосов
/ 16 ноября 2018

Ваша @OneToMany ассоциация получает лениво, что всегда должно быть вашим предпочтительным FetchType.Он работает намного лучше, чем выборка EAGER.

Но тогда вам нужно убедиться, что вы инициализировали все необходимые ассоциации, прежде чем закрыть Session или отправить объект сущности любому клиенту.В вашем случае маршалинг JSON происходит после закрытия сеанса, что вызвало исключение.

Существует несколько способов инициализации лениво извлеченной ассоциации .Самым простым является предложение JOIN FETCH в запросе JPQL, например:

SELECT p FROM Post p LEFT JOIN FETCH p.comments c WHERE p.id = :id

Если вы используете em.find для загрузки сущности Post, вам нужно либо заменить его на JPQLзапрос или используйте EntityGraph.

0 голосов
/ 15 ноября 2018

В сопоставлении один ко многим, определите тип выборки как EAGER.

@OneToMany(cascade = CascadeType.ALL,
        fetch = FetchType.EAGER,
        mappedBy = "post")
...