天天看點

SpringBoot從入門到精通(二十七)JPA實作自定義查詢,完全不需要寫SQL!一、預定義查詢二、自定義查詢三、自定義SQL語句四、已命名查詢最後

前面講了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自帶的方法。如下圖所示:

SpringBoot從入門到精通(二十七)JPA實作自定義查詢,完全不需要寫SQL!一、預定義查詢二、自定義查詢三、自定義SQL語句四、已命名查詢最後

我們看到,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實作了自定義的已命名查詢的功能。

SpringBoot從入門到精通(二十七)JPA實作自定義查詢,完全不需要寫SQL!一、預定義查詢二、自定義查詢三、自定義SQL語句四、已命名查詢最後

最後

以上就把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 版本控制!