Как загрузить данные OneToMany Collections в ответ с помощью FetchType.LAZY?

Я создал образец приложения jHipster (url: http://jhipster.github.io/creating_an_app.html), используя подгенератор сущностей, я создал сущность Event, которая имеет связь OneToMany с EventImages. , EventTickets и EventQuestions, когда я получаю все (приложение, работающее на локальном компьютере, URL-адрес API: http://127.0.0.1:8080/api/события ) события Мне не удалось найти данные EventImages, EventTickets и EventQuestions в ответ.

Объект события

@Entity
@Table(name = "JHI_EVENT")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Event implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

/* other fields */

@OneToMany(mappedBy = "event")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JsonIgnore
private Set<EventTicket> eventTickets = new HashSet<>();

@OneToMany(mappedBy = "event")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JsonIgnore
private Set<EventImage> eventImages = new HashSet<>();

@OneToMany(mappedBy = "event")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JsonIgnore
private Set<EventQuestion> eventQuestions = new HashSet<>();

/* getter and setters */

}

Объект EventImages

@Entity
@Table(name = "JHI_EVENTIMAGE")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class EventImage implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "image_url")
private String imageUrl;

@ManyToOne
private Event event;

 /* getters and setters */
}

аналогично сущности EventTickets и EventQuestions.

После некоторых исследований я обнаружил, что мне нужно удалить аннотацию @JsonIgnore для загрузки данных OneToMany Collections с использованием отложенной выборки, и я получил ответ null для EventImage, EventTicket и EventQuestions, как показано ниже.

[ {
"id": 1,
"title": "First Event",
"eventVenue": "xyz",
"startDate": "2015-05-28T10:10:00Z",
"endDate": "2015-06-20T10:10:00Z",
"eventTickets": null,
"eventImages": null,
"eventQuestions": null
 } ]

Затем я обнаружил, что мне нужно использовать @JsonManagedReference и @JsonBackReference для отношения родитель/потомок, но нужно использовать fetch = Fetch.EAGAR (я хочу загружать коллекции OneToMany, когда я устанавливаю FetchType.LAZY по умолчанию, как когда вызывается сущность Event).

Объект события, когда я использовал @JsonManagedReference

@Entity
@Table(name = "JHI_EVENT")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Event implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

/* other fields */

@OneToMany(mappedBy = "event", fetch = FetchType.EAGER)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JsonManagedReference
private Set<EventTicket> eventTickets = new HashSet<>();

@OneToMany(mappedBy = "event", fetch = FetchType.EAGER)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JsonManagedReference
private Set<EventImage> eventImages = new HashSet<>();

@OneToMany(mappedBy = "event", fetch = FetchType.EAGER)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JsonManagedReference
private Set<EventQuestion> eventQuestions = new HashSet<>();

/* getter and setters */

}

Объект EventImage, когда я использовал @JsonBackReference

@Entity
@Table(name = "JHI_EVENTIMAGE")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class EventImage implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "image_url")
private String imageUrl;

@ManyToOne
@JsonBackReference
private Event event;

 /* getters and setters */
}

Как загрузить коллекции OneToMany лениво, т. е. EventImages, EventTickets и EventQuestions, в ответ на запрос объекта Event, т. е. http://127.0.0.1:8080/api/events Выполняется вызов REST.

Спасибо


person Raj    schedule 26.05.2015    source источник


Ответы (1)


На самом деле я не понимаю вашего вопроса, но я пытаюсь объяснить, как работает JPA.

Как вы упомянули, используя JPA, вы можете загружать коллекции LAZILY или EAGERLY.

  • LAZY означает, что вы не загружаете коллекцию с самого начала. Коллекция загружается только тогда, когда вы обращаетесь к коллекции (это работает только в той же транзакции, в которой сущность загружается или прикрепляется).

  • EAGER означает, что коллекция загружается с самого начала (по мере загрузки самой сущности).

Поэтому, если вы хотите предоставить коллекцию службой REST, вам нужно загрузить коллекции во время транзакции.

Это можно сделать несколькими способами:

  • Один из способов — определить FetchType коллекции как EAGER.
  • Другой способ — лениво загрузить коллекцию и после загрузки объекта получить доступ к коллекции (например, вызвав size() -> event.getEventImages().size();)
  • Другой способ - загрузить объект и коллекцию с помощью JPQL-Query (SELECT e FROM Event JOIN FETCH e.eventImages...)
  • Есть еще больше способов добиться этого в зависимости от используемой реализации JPA.

Итак, если я правильно понял ваш вопрос, вы могли бы аннотировать свой Spring-Data-DAO-Find-Method с помощью

@Query("SELECT e FROM Event JOIN FETCH e.eventTickets, JOIN FETCH e.eventImages, JOIN FETCH e.eventQuestions")

person Lorenz Pfisterer    schedule 26.05.2015
comment
да.. вы правильно поняли, извините за опоздание. но если я использую event.getEventImages().size(); я получил org.hibernate.LazyInitializationException: не удалось лениво инициализировать набор ролей: com.urbanbinge.domain.Event.eventImages, не удалось инициализировать прокси - нет сеанса. - person Raj; 30.05.2015