2014-02-04 1 views
19

Я пытаюсь использовать HQL, получая мою сущность вместе с сущностями, используя JOIN FETCH, это работает нормально, если я хочу все результаты, но это не так, если я хочу A PageSpring-Data FETCH JOIN с пейджингом не работает

Моя сущность является

@Entity 
@Data 
public class VisitEntity { 

    @Id 
    @Audited 
    private long id; 

    . 
    . 
    . 

    @OneToMany(cascade = CascadeType.ALL,) 
    private List<VisitCommentEntity> comments; 
} 

и потому, что у меня есть миллионы посещений мне нужно использовать выгружаемой и я хочу, чтобы Fetch комментарии в один запрос к базе данных, как:

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

это HQL вызов выдает следующее исключение:

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) 

и однажды я удалить подкачки все работает отлично

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

Очевидно, что проблема в том, счетчик запросов от Spring-Data, но как мы можем это исправить?

ответ

35

Самый простой способ - использовать атрибут countQuery аннотации @Query для предоставления пользовательского запроса для использования.

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

ehh great but second line, 'countQuery =" select count (v) from VisitEntity v where ... ")' – azerafati

+1

Спасибо, это исправлено! :) –

+0

временный: Оливер мог бы и плз подтвердить это ?? http://stackoverflow.com/questions/21203875/difference-between-save-and-saveandflush-in-spring-data-jpa/21204100?noredirect=1#comment38102356_21204100 – azerafati

0

Вы должны указать countQuery параметров для @Query и теперь вы можете использовать Page или List в качестве возвращаемого значения.

@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<VisitEntity> getVenueVisits(@Param("venueId") long venueId,..., 
     Pageable pageable); 
+1

Нужно ли брать детей (например, 'v.comments') для' countQuery'? Или будет достаточно: 'SELECT count (v) FROM VisitEntity v WHERE v.venue.id =: venueId и ..." '? –

+0

Правильно, для countQuery, нет необходимости указывать выборку. – Max

0

Кроме того, в новых версиях Spring (поддержка JPA 2.1 спецификации), вы можете использовать сущности график так:

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

конечно же имени графов сущностей работать.