[踩雷紀錄] JPA 限制查詢筆數
2023, Jan 28
JPA 的功能強大,能利用介面名稱以及回傳類型建立相應的查詢語句,如果不夠用還可以透過 JPQL 自行組裝,不過最近遇到需要取用查詢結果排序後第一筆的時候遇到一些困難,紀錄一下解法
問題描述
因需求的 query 蠻複雜的所以是採用 JPQL 撰寫,但是撰寫的時候發現沒辦法用 LIMIT
如下面舉例
@Query("SELECT u FROM User u WHERE u.status = 1 ORDER BY createdAt DESC LIMIT 1")
public User findFirst();
上面的寫法是沒辦法執行的,JPQL 是不支援 LIMIT
語法的,令人有些納悶
解決辦法
Native Query
最簡單暴力的解決辦法就是直接改用原生語法
@Query(value = "SELECT * FROM `user` u WHERE u.status = 1 ORDER BY created_at DESC LIMIT 1", nativeQuery = true)
public User findFirst();
雖然可以簡單解決問題,但是寫原生語法是盡可能想避免的做法
Pageable 做為參數帶入
JPQL 無法直接寫 LIMIT
但可以透過傳入 Pageable
的物件來實現,我們可以改寫 DAO
的方法參數
@Query("SELECT u FROM User u WHERE u.status = 1")
public User findFirst(Pageable pageable);
使用的時候帶入參數
userDao.findFirst(PageRequest.of(0, 1, Sort.by("createdAt").descending()));
這才是比較符合 JPA 用法的做法,不過由於 Pageable 的參數有三個,通常會再包裝一層在 service 中調用
補充
其實如果不需要寫到客製化語法,透過 JPA 自己產生的實作是可以套用 LIMIT
的,如下範例
public List<User> findTop10ByOrderByCreatedAtDesc();
這樣可以產出能使用的語法,只是 method 會長一點
結語
JPA 的確是一個非常好用的 ORM 工具,在方便以及高度客製化中都提供方法實作,取得了很好的平衡,不過有時候這種便利的套裝也會引起一些問題跟誤用,需要對工具多加了解才能得心應手,發揮最大的效用