SpringData Jpa 使用@Query解決多表查詢、模糊查詢(空字段或者null判斷)、排序、分頁功能

本文是個人原創,轉載請說明文章出處。

此文數據庫爲mysql

使用jpa非常方便,可是感覺靈活性不如mybatis高,特別是自定義的查詢語句,往往無從下手,還好jpa提供了@Query註解,可以通過自定義原生的sql來查詢,這用起來就和mybatis一樣爽了,雖然入侵了代碼,但是從實現上來說,也並不是不可取的。畢竟用hibernate封裝的一些查詢來處理業務,在遇到需要修改查詢條件的時候,大多情況下還是要入侵代碼的,所以這裏不考慮應用的擴展,只是把自己使用過程中遇到的一些問題提供給大家,有更好的方案,歡迎留言。
只貼一個接口和測試類,其他的請自行參考。
Repository接口

public interface AbcRepository extends JpaRepository<Abc, String>, JpaSpecificationExecutor<Abc> {

 @Query(value = "SELECT a.* FROM abc" +
         "INNER JOIN (SELECT script_name,MAX(date_created) 'date_created' FROM abc" +
         "GROUP BY script_name) b " +
         "ON a.script_name = b.script_name  " +
         "AND a.date_created = b.date_created " +
         "AND IF(ifnull(?1,'') != '',a.script_name LIKE CONCAT('%',?1,'%'),1=1) " +
         "AND IF(ifnull(?2,'') != '',a.script_status LIKE CONCAT('%',?2,'%'),1=1) " +
         "AND IF(ifnull(?3,'') != '',a.script_flag LIKE CONCAT('%',?3,'%'),1=1) " +
         "AND IF(ifnull(?4,'') != '',a.level_one=?4,1=1) order by ?#{#pageable}",
         countQuery = "SELECT a.* FROM job_script a " +
                 "INNER JOIN (SELECT script_name,MAX(date_created) 'date_created' FROM job_script " +
                 "GROUP BY script_name) b " +
                 "ON a.script_name = b.script_name  " +
                 "AND a.date_created = b.date_created " +
                 "AND IF(ifnull(?1,'') != '',a.script_name LIKE CONCAT('%',?1,'%'),1=1)" +
                 "AND IF(ifnull(?2,'') != '',a.script_status LIKE CONCAT('%',?2,'%'),1=1) " +
                 "AND IF(ifnull(?3,'') != '',a.script_flag LIKE CONCAT('%',?3,'%'),1=1) " +
                 "AND IF(ifnull(?4,'') != '',a.level_one=?4,1=1)",
         nativeQuery = true)
 Page<abc> findJobScriptsByConditons(String scriptName,
                                           String scriptStatus,
                                           String scriptFlag,
                                           String levelOne,
                                           Pageable pageable);
}

測試類:

    @Test
    public void queryJobScriptByCondition() {
        Page<abc> auto = this
                .jobScriptRepository
                .findJobScriptsByConditons(
                        "",
                        "1",
                        "AUF",
                        "AUF",
                        new PageRequest(0,5));

        System.out.println("============================總數:" + auto.getTotalElements());
    }

可以將參數Pageable類封裝成帶排序的工具類,但是使用原生的sql時候,傳入的排序字段必須是mysql數據庫對應的,而不是實體對應的字段,比如最後一個參數new PageRequest(0,5)可以改爲:

PageUtil.buildPageable(currentPage,
                       rows,
                       Sort.Direction.DESC,
                       "date_created") //此處若是原生的SQL,必須用mysql數據庫字段,而不是實體類的駝峯命名的字段dateCreated

封裝後的分頁工具類:


public class PageUtil {

    public static Pageable buildPageable(int page, int size, Sort.Direction direction, String... orderFields) {
        Sort sort = null;
        Pageable pageable;
        if (null != orderFields && orderFields.length > 0) {
            if (null != direction) {
                sort = new Sort(direction, orderFields);
            } else {
                sort = new Sort(Sort.Direction.ASC, orderFields);
            }
        }
        if (null == sort) {
            pageable = new PageRequest(page, size);
        } else {
            pageable = new PageRequest(page, size, sort);
        }
        return pageable;
    }
}

代碼都經測試,如有錯誤之處,希望共同交流指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章