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

Създадох примерно приложение jHipster ( url: http://jhipster.github.io/creating_an_app.html), използвайки подгенератор на обект, създадох обект Събитие, който има връзка 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, което е по подразбиране, като при извикване на обект Събитие).

Обект на събитие, когато използвах @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 в отговор, когато обектът на събитие е поискан, т.е. http://127.0.0.1:8080/api/events Извършва се REST повикване.

Благодаря


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


Отговори (1)


Всъщност не разбирам въпроса ви, но се опитвам да обясня как работи JPA.

Както споменахте, с помощта на JPA можете да зареждате колекции ЛЕНИВО или НЕПЪЛНО.

  • 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