天天看點

JPA聲明式查詢關鍵字及使用方法

分享知識 傳遞快樂

使用JPA自定義聲明式查詢方法

凡是繼承了JpaRepository的或繼承其子接口的,都可以使用自定義的聲明式查詢方法。

聲明式查詢方法可以分3大類:

  • 計數類:以count開頭,傳回數值類型。
  • 查詢類:以get/find/stream/query/read開頭,傳回實體類或其集合。
  • 删除類:以delete/remove開始,傳回int類型。

示例:

public interface WebTaskRepository extends JpaRepository<WebTask, Integer> {
    // declare query method
    // 聲明式查詢方法 

    // 1. count 計數 
    long countByName(String name); 
    
    // 2. get/find/stream/query/read 查詢 
    public List<WebTask> findByTaskName(String name);
    
    // 3. delete/remove 删除 
    int deleteById(long id);
 }      

在以上方法之後還有可以加入下面的關鍵詞。

JPA聲明式查詢方法名稱關鍵詞

查詢方法可以由我們聲明的命名查詢生成,也可以像前面那樣由方法名解析。

  • 方法名以find…By, read…By, query…By, count…By和 get…By做開頭。在By之前可以添加Distinct表示查找不重複資料。By之後是真正的查詢條件。
  • 可以查詢某個屬性,也可以使用條件進行比較複雜的查詢,例如Between, LessThan, GreaterThan, Like,And,Or等。
  • 字元串屬性後面可以跟IgnoreCase表示不區分大小寫,也可以後跟AllIgnoreCase表示所有屬性都不區分大小寫。
  • 可以使用OrderBy對結果進行升序或降序排序。
  • 可以查詢屬性的屬性,直接将幾個屬性連着寫即可,如果可能出現歧義屬性,可以使用下劃線分隔多個屬性。
Keyword Sample JPQL snippet

​And​

​findByLastnameAndFirstname​

​… where x.lastname = ?1 and x.firstname = ?2​

​Or​

​findByLastnameOrFirstname​

​… where x.lastname = ?1 or x.firstname = ?2​

​Is,​

​​

​Equals​

​findByFirstname​

​,

​findByFirstnameIs​

​,

​findByFirstnameEquals​

​… where x.firstname = ?1​

​Between​

​findByStartDateBetween​

​… where x.startDate between ?1 and ?2​

​LessThan​

​findByAgeLessThan​

​… where x.age < ?1​

​LessThanEqual​

​findByAgeLessThanEqual​

​… where x.age <= ?1​

​GreaterThan​

​findByAgeGreaterThan​

​… where x.age > ?1​

​GreaterThanEqual​

​findByAgeGreaterThanEqual​

​… where x.age >= ?1​

​After​

​findByStartDateAfter​

​… where x.startDate > ?1​

​Before​

​findByStartDateBefore​

​… where x.startDate < ?1​

​IsNull​

​findByAgeIsNull​

​… where x.age is null​

​IsNotNull,​

​​

​NotNull​

​findByAge(Is)NotNull​

​… where x.age not null​

​Like​

​findByFirstnameLike​

​… where x.firstname like ?1​

​NotLike​

​findByFirstnameNotLike​

​… where x.firstname not like ?1​

​StartingWith​

​findByFirstnameStartingWith​

​… where x.firstname like ?1​

​​ (parameter bound with appended ​

​%​

​)

​EndingWith​

​findByFirstnameEndingWith​

​… where x.firstname like ?1​

​​ (parameter bound with prepended ​

​%​

​)

​Containing​

​findByFirstnameContaining​

​… where x.firstname like ?1​

​​ (parameter bound wrapped in ​

​%​

​)

​OrderBy​

​findByAgeOrderByLastnameDesc​

​… where x.age = ?1 order by x.lastname desc​

​Not​

​findByLastnameNot​

​… where x.lastname <> ?1​

​In​

​findByAgeIn(Collection<Age> ages)​

​… where x.age in ?1​

​NotIn​

​findByAgeNotIn(Collection<Age> ages)​

​… where x.age not in ?1​

​True​

​findByActiveTrue()​

​… where x.active = true​

​False​

​findByActiveFalse()​

​… where x.active = false​

​IgnoreCase​

​findByFirstnameIgnoreCase​

​… where UPPER(x.firstame) = UPPER(?1)​

具體文法規則和對應的sql都在代碼中給出來了,這邊需要和大家說的是UserRepository接口的特點。我們通過繼承JpaRepository《對應的實體類,主鍵屬性值》來編寫findBy等相關的函數來查詢資料庫。繼承JpaRepository的接口在使用的時候,通過@Autowired會自動建立接口的實作類,不需要怎麼去實作這個接口,這也是jpa最友善的地方。如果需要詳細說明的話可以檢視官方文檔​​Appendix C: Repository query keywords​​一節。

執行個體說明:

實體類

@Entity
@Table(name="user")
public class User {
  @Id
  @GenericGenerator(name = "PKUUID", strategy = "uuid2")
  @GeneratedValue(generator = "PKUUID")
  @Column(length = 36)
  protected String id;
  
  @Column(name = "name", nullable = true, length = 30)
  private String name;
  
  @Column(name = "height", nullable = true, length = 10)
  private Integer height;
  
  public User() {
  }
  
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Integer getHeight() {
    return height;
  }
  public void setHeight(Integer height) {
    this.height = height;
  }
}      

JPA

public interface UserRepository extends JpaRepository<User,String>{
  /**
  * 相當于 select *from user where name=?
  * @param name
  * @return
  */
  public List<User> findByName(String name);
  
  /**
  * 相當于select *from user where name like ?
  * 但是有一點需要注意的是,%需要我們自己來寫
  * @param name
  * @return
  */
  public List<User> findByNameLike(String name);
  
  /**
  * 相當于select *from user where name not like ?
  * 但是有一點需要注意的是,%需要我們自己來寫
  * @param name
  * @return
  */
  public List<User> findByNameNotLike(String name);
  
  /**
  * 相當于 select *from user where name <> ?
  * @param name
  * @return
  */
  public List<User> findByNameNot(String name);
  
  /**
  * 相當于 select *from user where id in (?)
  * @param ids
  * @return
  */
  public List<User> findByIdIn(List<String> ids);
  
  /**
  * 相當于 select *from user where id not in ()
  * @param ids
  * @return
  */
  public List<User> findByIdNotIn(List<String> ids);
  
  /**
  * 相當于 select *from user where name=? order by height desc
  * @param name
  * @return
  */
  public List<User> findByNameOrderByHeightDesc(String name);
  
  /**
  * 相當于 select *from user where name=? order by height asc
  * @param name
  * @return
  */
  public List<User> findByNameOrderByHeightAsc(String name);
  
  /**
  * 相當于 select *from user where name is null
  * @return
  */
  public List<User> findByNameIsNull();
  
  /**
  * 相當于 select *from user where name is not null
  * @return
  */
  public List<User> findByNameIsNotNull();
  
  /**
  * 相當于 select *from user where name =? and height=?
  * @param name
  * @param height
  * @return
  */
  public List<User> findByNameAndHeight(String name,int height);
  
  /**
  * 相當于 select *from user where name =? or height=?
  * @param name
  * @param height
  * @return
  */
  public List<User> findByNameOrHeight(String name,int height);
  
  /**
  * 相當于 select *from user where height between ? and ?
  * 需要注意的是mysql是有包含兩個端點值的
  * @param start
  * @param end
  * @return
  */
  public List<User> findByHeightBetween(int start,int end);
  
  /**
  * 相當于 select *from user where height < ?
  * 需要注意的是mysql是沒有包含端點值的
  * @param less
  * @return
  */
  public List<User> findByHeightLessThan(int less);
  
  /**
  * 相當于 select *from user where height > ?
  * 需要注意的是mysql是沒有包含端點值的
  * @param greater
  * @return
  */
  public List<User> findByHeightGreaterThan(int greater);
  
  //計數
  public Long countByName(String name);

  // 唯一查詢,findDistinctByTaskName == findDistinctUserByTaskName
  List<User> findDistinctTaskNameByTaskName(String name);

  // 啟用靜态排序
  List<User> findByNameOrderByIdDesc(String name);

  // 查詢符合查詢條件的前1條資料
  User findFirst1ByName(String name);

  // 獲得符合查詢條件的前2條資料
  List<User> findTop2ByName(String name);
}      

擴充:

JPA寫操作時需要注意,無論是更新,還是删除都需要加上@Transactional 和 @Modifying兩個注解。

@Modifying
@Transactional
@Query(value="DELETE FROM DS_IPAY_PAY T WHERE T.BILL_ID = ?1",nativeQuery=true)
public void delete(Long billId);