2015-02-15 31 views
10

Giả sử chúng tôi có một thực thể được gọi là MyEntity. Có thể truy vấn các kết quả có thể xem được bằng cách sử dụng @Query và với các truy vấn được đặt tên, ví dụ:Dữ liệu mùa xuân - Tại sao không thể phân trang với truy vấn gốc

@Query(value = "select e from MyEntity e where e.enabled = true") 
Page<MyEntity> findAllEnabled(Pageable pageable); 

Tuy nhiên, nó không phải là có thể đạt được cùng với truy vấn nguồn gốc, vì vậy đây

@Query(value = "select * from my_entity where enabled = true", nativeQuery = true) 
Page<MyEntity> findAllEnabled(Pageable pageable); 

sẽ không hoạt động.

Lý do đằng sau điều này là gì? Có thể đặt Pageable làm việc với các truy vấn gốc không?

+0

Thực ra, có thể. Xem [ở đây (Dữ liệu Mùa xuân và Truy vấn Gốc với phân trang)] (https://stackoverflow.com/q/38349930/1429387) để biết giải pháp. – naXa

Trả lời

10

Đây là mô tả, được đưa ra trong mùa xuân tài liệu dữ liệu JPA (http://docs.spring.io/spring-data/jpa/docs/1.8.0.M1/reference/html/)

Native queriesThe @Query chú thích cho phép để thực hiện các truy vấn nguồn gốc bằng cách thiết lập cờ nativeQuery là true. Lưu ý rằng chúng tôi hiện không hỗ trợ thực thi phân trang hoặc sắp xếp động cho truy vấn gốc vì chúng tôi phải thao tác truy vấn thực tế được khai báo và chúng tôi không thể thực hiện điều này một cách đáng tin cậy cho SQL nguyên gốc.

Tóm tắt JPQL Triển khai SQL và các chi tiết cụ thể của nhà cung cấp, đồng thời chịu trách nhiệm về khuôn khổ ORM để tạo SQL đúng.

  1. Vì vậy, bằng cách sử dụng Pagination ở dạng JPQL, Spring chỉ cần tạo JPQL chính xác và nó sẽ được hiểu trên cấp ORM để sửa SQL.

  2. Khi làm như vậy với SQL, có nghĩa là Spring biết cách tạo SQL đúng cho các đại đa số của RDBMS, nhân đôi chức năng ORM, quá nhiều chi phí.

21

Tôi không biết điều này vẫn còn phù hợp với bạn: Ít nhất trong Spring JPA dữ liệu 1.9.4 bạn có thể chỉ định hai truy vấn.

Với một kho lưu trữ:

interface FoobarEntityRepository extends JpaRepository<FoobarEntity, Integer> { 
    Page findFoobarsSpecialQuery(String someParameter, final Pageable pageable); 
} 

Bạn có thể thêm 2 truy vấn nguồn gốc từ thực thể của bạn, một cho truy vấn chính nó và một cho báo cáo kết quả đếm:

@Entity 
@SqlResultSetMappings({ 
    @SqlResultSetMapping(name = "SqlResultSetMapping.count", columns = @ColumnResult(name = "cnt")) 
}) 
@NamedNativeQueries({ 
    @NamedNativeQuery(
      name = "FoobarEntity.findFoobarsSpecialQuery", 
      resultClass = DailyPictureEntity.class, 
      query = "Select * from foobars f where someValue = :someParameter " 
    ), 
    @NamedNativeQuery(
      name = "FoobarEntity.findFoobarsSpecialQuery.count", 
      resultSetMapping = "SqlResultSetMapping.count", 
      query = "Select count(*) as cnt from foobars f where someValue = :someParameter " 
    ) 
}) 
FoobarEntity { 
} 

Bí quyết là để xác định truy vấn đếm với hậu tố .count. Điều này cũng làm việc với chú thích dữ liệu Spring @Query.

Lưu ý rằng bạn cần ánh xạ tập kết quả SQL cho truy vấn đếm.

Công trình này thực sự khá đẹp.

+0

Câu trả lời hay, làm việc như một sự quyến rũ! – SergeyB

+0

Cảm ơn câu trả lời, nó đã giải quyết được thử thách của tôi. –

3

Có một cách để sử dụng Có thể phân trang với truy vấn gốc có dung lượng SpEL của dữ liệu Spring, đề cập đến here.

Bạn có thể tìm thấy ví dụ trong this repository.

/** 
    * @see DATAJPA-564 
    */ 
    @Query(
      value = "select * from (select rownum() as RN, u.* from SD_User u) where RN between ?#{ #pageable.offset -1} and ?#{#pageable.offset + #pageable.pageSize}", 
      countQuery = "select count(u.id) from SD_User u", nativeQuery = true) 
    Page<User> findUsersInNativeQueryWithPagination(Pageable pageable); 

Các loại functionnality sẽ không hoạt động đúng nếu có một subquery trong mệnh đề from hoặc truy vấn mẹ đẻ của bạn và bạn muốn áp dụng một loại động trên đó. Cách nó có thể được thực hiện là di chuyển truy vấn con trong mệnh đề where.
Dữ liệu mùa xuân sẽ thêm vào kết thúc yêu cầu " order by " nếu có đối tượng Sort trong số Pageable. (với dữ liệu Spring 1.10.3)

Cách tốt hơn là chuyển đổi truy vấn gốc trong jpql nếu có thể.

+0

Atm có vẻ như có thể sử dụng chú thích @Query (không chắc chắn về bản địa) với các phương thức lưu trữ trả về các đối tượng Trang, mặc dù tôi tìm thấy các vấn đề khi tôi muốn chuyển truy vấn đến tệp orm.xml. Không cần truy vấn giá trị và đếm ... chỉ cần đặt truy vấn bình thường. – Rafael

Các vấn đề liên quan