JPA或Hibernate中使用原生SQL實現分頁查詢、排序


發生背景:前端展示的數據需要來自A表和D表拼接,A表和D表根據A表的主鍵進行關聯,D表的非主鍵字段關聯C表的主鍵,根據條件篩選出符合的數據,並且根據A表的主鍵關聯B表的主鍵(多主鍵)的條件,過濾A表中不符合的數據。因為數據量較大,所以需要進行分頁。
環境:DM DatabaseJ(達夢數據庫,和Oracle差不多),JPA
使用@Query注解,使用value屬性來聲明查詢SQL,countQuery屬性取得當前查詢的數量,nativeQuery屬性聲明為true,表示為支持當前的SQL語句為原生SQL。

ServiceImpl:
1 Sort sort = new Sort(Sort.Direction.DESC, "slrq");
2 Pageable pageable = PageRequest.of(pageNum, pageSize, sort);

Repository:
@Query(value = "SELECT aj.ajmc AS ajmc, " +
                "aj.ajlb_bm AS ajlbbm, " +
                "aj.ajlb_mc AS ajlbmc, " +
                "aj.cbdw_bm AS cbdwbm, " +
                "aj.cbdw_mc AS cbdwmc, " +
                "aj.cbjcg AS cbjcg, " +
                "aj.bmsah AS bmsah, " +
                "rz.ysdw_dwdm AS ysdwdm, " +
                "rz.ysdw_dwmc AS ysdwmc, " +
                "rz.ysay_aydm AS ysaydm, " +
                "rz.ysay_aymc AS ysaymc " +
                "FROM aj_yx_aj aj " +
                "INNER JOIN aj_yx_slrz rz ON aj.bmsah = rz.bmsah " +
                "INNER JOIN aj_xt_sldy dy ON rz.slbh = dy.slbm " +
                "WHERE aj.sfsc = 'N' " +
                "AND aj.cbdw_bm = :cbdwbm " +
                "AND (aj.ajmc like :gjz OR aj.cbjcg like :gjz) " +
                "AND aj.ajzt = '1' " +
                "AND (SELECT COUNT(ry.zrrbm) FROM tyyw_gg_zrrsjls ry WHERE ry.bmsah = aj.bmsah " +
                "AND ry.zrrlx_dm = '0009000900001' " +
                "AND ry.sfsc = 'N') > 1 " +
                "AND dy.sllb = '1' " +
                "AND rz.sfsc = 'N' " +
                "AND dy.sfsc = 'N'  ",
        countQuery = "SELECT COUNT(*) FROM " +
                "(SELECT * FROM aj_yx_aj aj " +
                "INNER JOIN aj_yx_slrz rz ON aj.bmsah = rz.bmsah " +
                "INNER JOIN aj_xt_sldy dy ON rz.slbh = dy.slbm " +
                "WHERE aj.sfsc = 'N' " +
                "AND aj.cbdw_bm = :cbdwbm " +
                "AND (aj.ajmc like :gjz OR aj.cbjcg like :gjz) " +
                "AND aj.ajzt = '1' " +
                "AND (SELECT COUNT(ry.zrrbm) FROM tyyw_gg_zrrsjls ry WHERE ry.bmsah = aj.bmsah " +
                "AND ry.zrrlx_dm = '0009000900001' " +
                "AND ry.sfsc = 'N') > 1 " +
                "AND dy.sllb = '1' AND rz.sfsc = 'N' AND dy.sfsc = 'N' )", nativeQuery = true)
//repository層的調用方法
Page<Map> findCalb(@Param("cbdwbm") String dwbm, @Param("gjz") String gjz, Pageable pageable);

注意:
  1、方法傳入參數中的Pageable參數,在SQL並沒有使用這樣一個參數,但是pageable中的page參數和sort參數會在查詢時自動拼接到末尾,因此就達到了原生SQL實現分頁排序的效果
  2、可能會出現這樣一個問題:查詢出來的Page.content中,所有數據可能只有值,而不是“字段名:字段值”的key-value屬性,那么這樣的數據就沒有任何意義,也無法讓前端取得任何字段的值。
  解決辦法:在調用方法返回的Page類型后面加上一個Map類型即可解決。

可能大家在百度這個問題時,會發現很多回答都是在sql語句最后面加上”/#pageable/“這樣一個參數,但是會發現這個並沒有用,甚至還會報錯:解析SQL語句出錯。
(如:https://blog.csdn.net/github_34645245/article/details/81359519 中的回答)


這次問題是在工作中發現的,最重解決辦法是根據本人慢慢摸索出來的,但是可能並不適用所有情況(如Mysql數據庫、其他ORM框架等等均沒有測試)。如果大家發現還存在其他問題,歡迎在評論區指正。
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM