Spring-Data FETCH JOIN con Paging non funziona

Sto cercando di usare HQL per il recupero della mia quadro insieme alle sotto quadro usando JOIN FETCH, questo funziona bene se voglio tutti i risultati ma non è il caso se voglio una pagina

La mia quadro è

@Entity @Data public class VisitEntity { @Id @Audited private long id; . . . @OneToMany(cascade = CascadeType.ALL,) private List comments; } 

e poiché ho milioni di visite ho bisogno di usare Pageable e voglio recuperare i commenti in una singola query del database come:

 @Query("SELECT v FROM VisitEntity v LEFT JOIN FETCH v.comments WHERE v.venue.id = :venueId and ..." ) public Page getVenueVisits(@Param("venueId") long venueId,..., Pageable pageable); 

Quella chiamata HQL lancia la seguente eccezione:

 Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=null,role=com.ro.lib.visit.entity.VisitEntity.comments,tableName=visitdb.visit_comment,tableAlias=comments1_,origin=visitdb.visit visitentit0_,columns={visitentit0_.visit_id ,className=com.ro.lib.visit.entity.VisitCommentEntity}}] [select count(v) FROM com.ro.lib.visit.entity.VisitEntity v LEFT JOIN FETCH v.comments WHERE v.venue.id = :venueId and (v.actualArrival > :date or v.arrival > :date)] at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1374) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310) at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:309) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 

e una volta rimosso il paging, tutto funziona correttamente

 @Query("SELECT v FROM VisitEntity v LEFT JOIN FETCH v.comments WHERE v.venue.id = :venueId and ..." ) public List getVenueVisits(@Param("venueId") long venueId,...); 

Ovviamente il problema è la query di conteggio di Spring-Data, ma come possiamo risolverlo?

Il modo più semplice è utilizzare l’attributo @Query dell’annotazione @Query per fornire una query personalizzata da utilizzare.

 @Query(value = "SELECT v FROM VisitEntity v LEFT JOIN FETCH v.comments …", countQuery = "select count(v) from VisitEntity v where …") List getVenueVisits(@Param("venueId") long venueId, …); 

Devi specificare il parametro countQuery per @Query e ora puoi usare Page o List come valore di ritorno.

 @Query(value = "SELECT v FROM VisitEntity v LEFT JOIN FETCH v.comments WHERE v.venue.id = :venueId and ...", countQuery = "SELECT count(v) FROM VisitEntity v LEFT JOIN v.comments WHERE v.venue.id = :venueId and ..." ) public Page getVenueVisits(@Param("venueId") long venueId,..., Pageable pageable); 

In alternativa, nelle ultime versioni di Spring (che supportano le specifiche JPA 2.1) puoi usare un grafico delle quadro come questo:

 @EntityGraph(attributePaths = "roles") @Query("FROM User user") Page findAllWithRoles(Pageable pageable); 

Ovviamente funzionano anche i grafici delle entity framework con nomi.