SpringData JPA的常用語法匯總

前言

SpringData JPA常用有兩種寫法,一個是用Jpa自帶方法進行CRUD,適合簡單查詢場景、例如查詢全部數據、根據某個字段查詢,根據某字段排序等等。另一種是使用註解方式,@Query@Modifying

1.方法方式

方法說明

接口方法如下,方法作用見註釋:

public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
    // 無條件,查詢全部記錄
    List<T> findAll();
    // 排序查詢
    List<T> findAll(Sort var1);
    // 根據主鍵ID查詢
    List<T> findAllById(Iterable<ID> var1);
    // 批量保存集合數據
    <S extends T> List<S> saveAll(Iterable<S> var1);

    void flush();
 
    <S extends T> S saveAndFlush(S var1);
    // 批量刪除
    void deleteInBatch(Iterable<T> var1);
    // all in 全部刪除
    void deleteAllInBatch();
    // 查詢一條記錄
    T getOne(ID var1);
    // 條件查詢
    <S extends T> List<S> findAll(Example<S> var1);
    // 條件查詢,帶排序
    <S extends T> List<S> findAll(Example<S> var1, Sort var2);
}

例子

一般dao實現JpaRepository接口,直接調用JpaRepository中的方法就可以實現瞭簡單查詢,例如查詢User實例列表:

// 構建user的Example對象
Example<User> example =Example.of(User);
List<User> users = userRepository.findAll(example);

2.註解方式

jpa實現CRUD的主要註解是@Query

註解說明

@Query註解主要有以下參數,參數作用如下:

  • value:SQL語句
  • countQuery: 分頁查詢時統計總數
  • nativeQuery: 使用執行這個方法的時候執行原生sql語句,直接寫數據庫中的實際表名和表的實際字段名

@Query的代碼如下:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@QueryAnnotation
@Documented
public @interface Query {
    String value() default "";
    String countQuery() default "";
    String countProjection() default "";
    boolean nativeQuery() default false;
    String name() default "";
    String countName() default "";
}

例子

  • 使用註解方式分組查詢

跟正常寫sql語句相同,將sql寫到value中,並且nativeQuery = true。下面例子是根據task_id進行分組查詢task集合

@Query(value = "select task_id from task group by task_id", nativeQuery = true)
List<Task> queryByGroup();
  • 使用註解方式排序

根據task_id進行排序查詢task集合

@Query(value = "select task_id,task_date from task order by task_id", nativeQuery = true)
List<Task> queryOrder();
  • 使用註解方式條件查詢

條件查詢時可以使用字段名 操作符 ?;例如:task_date >= ?,使用位置匹配?。也可以使用字段名 操作符 :屬性名;例如:task_date >= :startDate,使用屬性名匹配,推薦使用後者,如果字段順序修改,不影響匹配結果。下面是根據任務時間(task_date)段內和未被刪除(deleted)的任務

@Query(value = "select task_id,task_date from task where task_date >=? and task_date <=? and deleted=0 ", nativeQuery = true)
List<ApptTask> queryDate(@Param("startDate") String startDate, @Param("endDate") String endDate);
  • 使用註解方式修改

修改一條數據需要加上@Modifying用於標識是修改操作,默認事務等級是隻讀,所以還需要加上@Transactional,這樣覆蓋瞭默認的@Transactional才可以執行修改操作。下面是根據task_id更新task表的備註信息

@Transactional(rollbackOn = Exception.class)
@Modifying
@Query(value = "update task set remark = ? where task_id=?", nativeQuery = true)
void updateRemark(@Param("remark") String remark, @Param("taskId") String taskId);

多表聯查,且多條件、分頁查詢怎麼寫?

復雜的查詢需要註意,以下使用一個Mysql的多表聯查的例子來說明復雜的查詢要怎麼寫。下面是usertask表關聯查詢出任務名稱、任務ID、用戶名稱這些信息,並且根據task_nametask_date進行過濾;根據task_date倒序。

共有幾點需要註意:

  • 多表聯查使用正常的JOIN就可以
  • 多條件是常見的情況,需要區別傳入的條件是否要去執行,這種情況需要使用where 1=1 and 這種方式來保證條件不傳時仍然正常查詢。
  • 分頁查詢需要傳入分頁參數Pageable,並且寫countQuery來統計總數。
  • 多條件查詢關鍵:if(:參數!='',k.字段名 =:參數,1=1),這裡是使用瞭if進行判斷,這個寫法類似Mybatis xml中的<if>標簽。if的含義是代表傳入的參數如果不為""(Spring類型空是""而不是null)將參數傳入,如果為空時顯示1=1 代表參數為真,對查詢結果不產生作用。

代碼:

@Query(value =
      " select a.task_name, a.task_id,u.user_name" +
      " from task a " +
      " LEFT JOIN usert u" +
      " ON a.user_id = u.user_id" +
      " where  a.deleted=0  " +
      " AND if(:taskName!='',a.task_name =:taskName,1=1)" +
      " AND if(:startDate!='',a.task_date >=:startDate,1=1)" +
      " AND if(:endDate!='',a.task_date <=:endDate,1=1)" +
      " order by a.task_date desc"
      , 
      nativeQuery = true
      , 
      countQuery =
      " select count(*)" +
      " from task a " +
      " LEFT JOIN usert u" +
      " ON a.user_id = u.user_id" +
      " where  a.deleted=0  " +
      " AND if(:taskName!='',a.task_name =:taskName,1=1)" +
      " AND if(:startDate!='',a.task_date >=:startDate,1=1)" +
      " AND if(:endDate!='',a.task_date <=:endDate,1=1)" +
      " order by a.task_date desc")
Page<Map<String,Object>> queryUserTaskPage(@Param("taskName") String taskName, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate, @Param("pageable") Pageable pageable);

小結

以上列舉瞭兩種JPA的crud方式,jpa方法與註解方式,平時寫代碼時更傾向於使用註解方式去寫原生sql來實現業務。對於簡單查詢可以用JpaRepository裡面這些方法就夠用瞭,對於更復雜的場景推薦使用@Query寫sql的方式來實現。

jpa方法可以屏蔽底層的sql,如果有不同數據庫實現的服務,用jpa方法可以免於修改sql。但是jpa方法對於分組查詢、limit支持、多條件、多表聯查這些不太友好。

總結

到此這篇關於SpringData JPA常用語法的文章就介紹到這瞭,更多相關SpringData JPA常用語法內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: