前面講了Spring Boot 整合Spring Boot JPA,實作JPA 的增、删、改、查的功能。JPA使用非常簡單,隻需繼承JpaRepository ,無需任何資料通路層和sql語句即可實作完整的資料操作方法。
JPA除了這些功能和優勢之外,還有非常強大的查詢的功能。以前複查的查詢都需要拼接很多查詢條件,JPA 有非常友善和優雅的方式來解決。Spring Data JPA 查詢分為三種:
1、Spring Data JPA 預設實作的預定義的方法
2、需要根據查詢的情況定義查詢條件
3、通過@Query 注解,自定義hql 查詢語句
接下來就聊一聊JPA 自定義查詢,體驗Spring Data JPA 的強大。
一、預定義查詢
預定義方法就是我們上面看到的那些自帶的方法,因為UserRepository繼承了 JpaRepository 擁有了父類的這些JPA自帶的方法。如下圖所示:

我們看到,JpaRepository類預設自帶了很多資料操作方法,包括save、delete、findAll、fidById、等方法。調用這些預定義的預定義方法也非常簡單,具體如下所示:
@RequestMapping("/test")
public void test() {
Users user = new Users();
user.setId((long) 1);
userRespository.findById((long) 1);
userRespository.findAll();
userRespository.delete(user);
userRespository.deleteById((long) 1);
userRespository.existsById((long) 1);
}
上面所有JpaRepository父類擁有的方法都可以直接調用 。
二、自定義查詢
Spring Data JPA 支援根據實體的某個屬性實作資料庫操作,主要的文法是 findByXX、 readAByXX、queryByXX、 countByXX、 getByXX 後跟屬性名稱。
利用這個功能僅需要在定義的 Repository 中添加對應的方法名即可,無需具體實作完整的方法,使用時 Spring Boot 會自動動幫我們實作對應的sql語句。
1、屬性查詢
根據姓名查詢,示例如下:
@Repository
public interface UserRespository extends JpaRepository<Users, Long> {
Users findByName(String name,String account);
}
上面的執行個體可以看到,我們可以在UserRepository 接口中進行接口聲明。例如,如果想根據實體的 name和account 這兩個屬性來進行查詢User的資訊。那麼直接在 UserRepository 中增加一個接口聲明即可。
2、組合條件查詢
JPA不僅支援單個屬性查詢,還能支援多個屬性,根據And、or 等關鍵字組合查詢:
Users findByNameAndAccount(String name,String account);
上面的例子,就是根據姓名和賬号兩個條件組合查詢。這個是組合查詢的例子,删除和統計也是類似的:deleteByXXAndXX、countByXXAndXX。可以根據查詢的條件不斷地添加和拼接, Spring Boot 都可以正确解析和執行。
3、JPA關鍵字
JPA的自定義查詢除了And、or 關鍵字外,基本上SQL文法中的關鍵字,JPA都支援,比如:like,between 等。
這個語句結構可以用下面的表來說明:
關 鍵 字 | 示例方法 | JPQL語句 |
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 |
三、自定義SQL語句
上面介紹了JPA的很多條件查詢的方法。但是,實際項目中,還是有些場景上面的查詢條件無法滿足。那麼我們就可以通過 @Query 注解寫hql 來實作。
@Query("select u from Users u where u.name = :name1")
List<UserDO> findByHql(@Param("name1") String name1);
說明:
1、@Query 注解,表示用執行hql語句。
2、name1等參數對應定義的參數。
上面是通過hql,如果hql 寫着不習慣,也可以用本地 SQL 語句來完成查詢:
@Query(value = "select * from users where name = ?1",nativeQuery = true)
List<User> findUserBySql(String name);
上面示例中的 ?1 表示方法參數中的順序,nativeQuery = true 表示執行原生sql語句。
四、已命名查詢
除了使用 @Query注解外,還可以使用@NamedQuery與@NameQueries等注解定義命名查詢。JPA的命名查詢實際上就是給SQL查詢語句起一個名字,執行查詢時就是直接使用起的名字,避免重複寫JPQL語句,使得查詢方法能夠複用。下面通過示例程式示範JPA已命名查詢。
1. 定義命名查詢
在實體類中,@NamedQuery注解定義一個命名查詢語句,示例代碼如下:
@Entity
@Table(name="t_user")
@NamedQuery(name="findAllUser",query="SELECT u FROM User u")
public class User {
// Entity實體類相關定義
}
在上面的示例中,@NamedQuery中的name屬性指定命名查詢的名稱,query屬性指定命名查詢的語句。如果要定義多個命名查詢方法,則需要使用@NamedQueries注解:
@Entity
@Table(name="users")
@NamedQueries({
@NamedQuery(name="findAllUser",query="SELECT u FROM User u"),
@NamedQuery(name="findUserWithId",query="SELECT u FROM User u WHERE u.id = ?1"),
@NamedQuery(name="findUserWithName",query="SELECT u FROM User u WHERE u.name = :name")
})
public class User {
// Entity實體類相關定義
}
在上面的示例中,在User實體類中定義了findAllUser()、findUserWithId()、findUserWithName()三種方法。
2. 調用命名查詢
定義命名查詢後,可以使用EntityManager類中的createNamedQuery()方法傳入命名查詢的名稱來建立查詢:
@Resource
EntityManagerFactory emf;
@Test
public void testNamedQuery() {
EntityManager em = emf.createEntityManager();
Query query = em.createNamedQuery("findUserWithName");// 根據User實體中定義的命名查詢
query.setParameter("name", "weiz");
List<User> users = query.getResultList();
for (User u : users){
System.out.println("name:"+u.getName()+",age:"+u.getAge());
}
}
在上面的示例中,使用createNamedQuery建立對應的查詢,JPA會先根據傳入的查詢名查找對應的NamedQuery,然後通過調用getResultList()方法執行查詢并傳回結果。
3. 運作驗證
單擊Run Test或在方法上右擊,選擇Run 'testNamedQuery',運作全部測試方法,結果如圖9-7所示。定義的已命名查詢findUserWithName的單元測試運作成功,并輸出了相應的查詢結果,說明使用JPA實作了自定義的已命名查詢的功能。
最後
以上就把Spring Data JPA的查詢功能介紹完了, JPA 簡化了我們對資料庫的操作,預定義很多常用的資料庫方法,直接使用即可。另外 JPA 還有一個特點,就是不用關心資料庫的表結構,需要更改的時候隻需要修改對應 Model 的屬性即可。
推薦閱讀:
SpringBoot從入門到精通(二十六)超級簡單的資料持久化架構!Spring Data JPA 的使用! SpringBoot從入門到精通(二十五)搞懂自定義系統配置 SpringBoot從入門到精通(二十四)3分鐘搞定Spring Boot 多環境配置! SpringBoot從入門到精通(二十三)Mybatis系列之——實作Mybatis多資料源配置 SpringBoot從入門到精通(二十二)使用Swagger2優雅建構 RESTful API文檔 SpringBoot從入門到精通(二十一)如何優雅的設計 RESTful API 接口版本号,實作 API 版本控制!