Trong một ứng dụng web sử dụng JPA Spring Data với Hibernate, chúng tôi sử dụng chức năng web pagination để cung cấp khả năng phân trang và sắp xếp trong các danh sách các thực thể khác nhau.Dữ liệu Spring JPA Các tham số page.sort không hợp lệ
@Controller
public class MyEntityController {
@RequestMapping(method = RequestMethod.GET)
public ModelAndView list(Pageable pageable) { ... }
}
@Configuration
public class MyWebMvcConfig extends WebMvcConfigurationSupport {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
super.addArgumentResolvers(argumentResolvers);
argumentResolvers.add(new PageableArgumentResolver());
}
}
public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, String> {
Page<MyEntity> findByPropertyX(String propertyX, Pageable pagable);
}
Điều này cho phép tính thực thể được xác định trong html rendered như loại đặc biệt request parameters, trong đó giá trị page.sort
thực sự phù hợp với một tài sản trong thực thể mà trên đó để sắp xếp.
<table>
<thead>
<tr>
<th><a href="?page.sort=propertyX&page.sort.dir=asc">Property X</a></th>
<th><a href="?page.sort=propertyY&page.sort.dir=asc">Property Y</a></th>
</tr>
</thead>
<tbody>...</tbody>
</table>
này tạo ra một URL kết quả như:
http://host/context-root/entities/?page.sort=propertyX&page.sort.dir=asc
Vấn đề là người dùng có thể thay đổi URL để sử dụng không hợp lệ page.sort
tài sản mà một trong hai tài liệu tham khảo không tồn tại tên cột/tài sản, hoặc tệ hơn, sử dụng các ký tự truy vấn JPA không hợp lệ dẫn đến cú pháp không hợp lệ.
Ví dụ, nếu URL được sửa đổi để sắp xếp vào "noSuchProperty":
http://host/context-root/entities/?page.sort=noSuchProperty&page.sort.dir=asc
Nhưng tài sản này không tồn tại, ngoại trừ sau đây sẽ được ném:
java.lang.IllegalArgumentException: No property noSuchProperty found for type class com.my.company.MyEntity
at org.springframework.data.repository.query.parser.Property.<init>(Property.java:76)
. . .
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:86)
. . .
at $Proxy68.findByPropertyX(Unknown Source)
at com.my.company.MyEntityRepository.findByPropertyX(MyEntityRepository.java:17
Tương tự như vậy, nếu URL được sửa đổi thành ký tự cú pháp truy vấn không hợp lệ, chẳng hạn như "" ":
http://host/context-root/entities/?page.sort=%22&page.sort.dir=asc
hoặc sẽ xảy ra:
java.lang.StackOverflowError
java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
. . .
org.springframework.data.repository.query.parser.Property.create(Property.java:326)
org.springframework.data.repository.query.parser.Property.create(Property.java:326)
org.springframework.data.repository.query.parser.Property.create(Property.java:326)
org.springframework.data.repository.query.parser.Property.create(Property.java:326)
(Ngoài ra còn có một hương vị thứ ba trường hợp ngoại lệ mà kết quả trong một org.hibernate.QueryException
khi @Query
được định nghĩa một cách rõ ràng về phương pháp Repository.)
mùa xuân dữ liệu JPA tóm tắt đi các chi tiết của phân loại, phân trang và xử lý các thông số này; tuy nhiên, nó dường như không xử lý các kịch bản này một cách duyên dáng (tức là khi một tham số sắp xếp không hợp lệ được chỉ định).
Chúng tôi có thể thêm vào một số logic tùy chỉnh bổ sung để xác thực rằng thuộc tính sắp xếp thực sự tồn tại trên thực thể; tuy nhiên, tôi tự hỏi liệu có cách tiếp cận tập trung rõ ràng hơn để làm điều này sao cho chúng ta không bị mất các lợi ích và sự đơn giản của trừu tượng JPA dữ liệu Spring. Chúng tôi sử dụng khả năng sắp xếp này trong ứng dụng của chúng tôi với nhiều thực thể khác nhau, vì vậy, lý tưởng, chúng tôi muốn có thêm một cách tiếp cận chung, thay vì phải xác định rõ ràng hoặc kiểm tra thuộc tính sắp xếp cho mọi trang thực thể được yêu cầu.
Cụ thể, chúng tôi thực sự mở rộng PageableArgumentResolver
để chấp nhận giá trị mặc định được sắp xếp chú thích được cung cấp trong bộ điều khiển của chúng tôi (không minh họa trong các ví dụ mã đơn giản), vì vậy chúng tôi muốn dự phòng theo thứ tự sắp xếp mặc định này hoặc chỉ là thứ tự sắp xếp mặc định cho thực thể, thay vì ném một ngoại lệ.
Một số ý tưởng và nỗ lực .. Tôi có thể sử dụng một QueryCreationListener
để chặn tạo truy vấn và nhận tham số sắp xếp; tuy nhiên, tôi thực sự không thể sửa đổi truy vấn tại thời điểm đó. Hoặc, tôi có thể mở rộng và sử dụng một tùy chỉnh PageableArgumentResolver
(chúng tôi đã làm điều này) để lấy các tham số sắp xếp; tuy nhiên, tôi không có quyền truy cập vào thực thể tại thời điểm đó, cũng như không thể xác định xem thực thể có thuộc tính có tên đó hay không.Chúng tôi có thể khai báo các thuộc tính được hỗ trợ một cách rõ ràng; tuy nhiên, một lần nữa, điều này đánh bại ý tưởng tập trung và tự động xử lý kịch bản này mà không yêu cầu kiến thức cụ thể hoặc được khai báo của các thực thể.
Có loại trình chặn chặn hoặc cấu trúc tương tự nào khác mà tôi có thể sử dụng để xác thực tập trung các thông số sắp xếp trang và sửa đổi nếu cần thiết trước khi gọi truy vấn không? Hoặc là có bất kỳ loại cấu hình hoặc cách mà Spring có thể tự động xử lý kịch bản này sao cho nó xử lý các tham số sắp xếp không hợp lệ một cách duyên dáng hơn?