【Spring Boot】JPA 的查詢方式

JPA 的查詢方式

  • 1.使用約定方法名
  • 2.用 JPQL 進行查詢
  • 3.用原生 SQL 進行查詢
    • 3.1 根據 ID 查詢用戶
    • 3.2 查詢所有用戶
    • 3.3 根據 email 查詢用戶
    • 3.4 根據 name 查詢用戶,并返回分頁對象 Page
    • 3.5 根據名字來修改 email 的值
    • 3.6 使用事務
  • 4.用 Specifications 進行查詢
  • 5.用 ExampleMatcher 進行查詢
  • 6.用謂語 QueryDSL 進行查詢
  • 7.用 NamedQuery 進行查詢

1.使用約定方法名

約定方法名一定要根據命名規范來寫,Spring Data 會根據前綴、中間連接詞(OrAndLikeNotNull 等類似 SQL 中的關鍵詞)、內部拼接 SQL 代理生成方法的實現。

約定方法名的方法見下表(不完全示例):

SQL
方法例子
JPQL 語句
andfindByLastnameAndFirstnamewhere x.lastname = ?1 and x.firstname = ?2
orfindByLastnameOrFirstnamewhere x.lastname = ?1 or x.firstname = ?2
=findByFirstname / findByFirstnameIs / findByFirstnameEqualswhere x.firstname = ?1

接口方法的命名規則也很簡單,只要明白 AndOrIsEqualGreaterStartingWith 等英文單詞的含義,就可以寫接口方法。具體用法如下:

public interface UserRepository extends Repository<User, Long> {List<User> findByEmailOrName(String email, String name);
}

上述代碼表示,通過 emailname 來查找 User 對象。

約定方法名還可以支持以下幾種語法:

  • User findFirstByOrderByNameAsc()
  • Page<User> queryFirst100ByName(String name, Pageable pageable)
  • Slice<User> findTop100ByName(String name, Pageable pageable)
  • List<User> findFirst100ByName(String name, Sort sort)
  • List<User> findTop100ByName(String name, Pageable pageable)

2.用 JPQL 進行查詢

JPQL 語言(Java Persistence Query Language)是一種和 SQL 非常類似的中間性和對象化查詢語言,它最終會被編譯成針對不同底層數據庫的 SQL 語言,從而屏蔽不同數據庫的差異。

JPQL 語言通過 Query 接口封裝執行,Query 接口封裝了執行數據庫查詢的相關方法。調用 EntityManager 的 Query、NamedQuery 及 NativeQuery 方法可以獲得查詢對象,進而可調用 Query 接口的相關方法來執行查詢操作。

JPQL 是面向對象進行查詢的語言,可以通過自定義的 JPQL 完成 UPDATE 和 DELETE 操作。JPQL 不支持使用 INSERT。對于 UPDATE 或 DELETE 操作,必須使用注解 @Modifying 進行修飾。

JPQL 的用法見以下兩段代碼。

(1)下面代碼表示根據 name 值進行查找。

public interface UserRepository extends JpaRepository<User, Long> (@Query("select u from User u where u.name = ?1")User findByName(String name);
}

(2)下面代碼表示根據 name 值進行模糊查找。

public interface UserRepository extends JpaRepository<User, Long> { @Query("select u from User u where u.name like %?1")List<User> findByName(String name);
}

3.用原生 SQL 進行查詢

在使用原生 SQL 查詢時,也使用注解 @Query。此時,nativeQuery 參數需要設置為 true。 下面先看一些簡單的查詢代碼。

3.1 根據 ID 查詢用戶

public interface UserRepository extends JpaRepository<User, Long> (// 根據 ID 查詢用戶@Query(value = "select * from user u where u.id=:id", nativeQuery = true)User findById(@Param("id")Long id);
)

3.2 查詢所有用戶

public interface UserRepository extends JpaRepository<User, Long> {// 查詢所有用戶@Query(value = "select * from user", nativeQuery = true)List<User> findAllNative();
}

3.3 根據 email 查詢用戶

public interface UserRepository extends JpaRepository<User, Long> (// 根據 email 查詢用戶@Query(value = "select * from user where email= ?1", nativeQuery = true) User findByEmail(String email);
)

3.4 根據 name 查詢用戶,并返回分頁對象 Page

public interface UserRepository extends JpaRepository<User, Long> (@Query(value = "select * from user where name= ?1",countQuery = "select count(*) from user where name= ?1", nativeQuery = true)Page<User> findByName(String name, Pageable pageable);
}

3.5 根據名字來修改 email 的值

@Modifying 
@Query("update user set email = :email where name =:name")
Void updateUserEmailByName(@Param("name")String name, @Param("email")String email);

3.6 使用事務

UPDATE 或 DELETE 操作需要使用事務。此時需要先定義 Service 層,然后在 Service 層的方法上添加事務操作。

對于自定義的方法,如果需要改變 Spring Data 提供的事務默認方式,則可以在方法上使用注解 @Transactional,如以下代碼:

@Service
public classUserService {@Autowiredprivate UserRepository userRepository;@Transactionalpublic void updateEmailByName(String name, String email) {userRepository.updateUserEmaiByName(name, email);}
)

測試代碼:

@Test
public void testUsingModifingAnnotation() {userService.updateEmailByName("pipi", "88888888@qq.com");
}

在進行多個 Repository 操作時,也應該使這些操作在同一個事務中。按照分層架構的思想,這些操作屬于業務邏輯層,因此需要在 Service 層實現對多個 Repository 的調用,并在相應的方法上聲明事務。

4.用 Specifications 進行查詢

如果要使 Repository 支持 Specification 查詢,則需要在 Repository 中繼承 JpaSpecificationExecutor 接口,具體使用見如下代碼:

public interface CardRepository extends JpaRepository<Card,Long>, JpaSpecificationExecutor<Card> {Card findById(long id);
}

下面以一個例子來說明 Specifications 的具體用法:

@SpringBootTest
@RunWith(SpringRunner.class)
public class testJpaSpecificationExecutor (@Autowiredprivate CardRepository cardRepository;@Testpublic void testJpaSpecificationExecutor() (int pageNo = 0;int pageSize = 5;PageRequest pageable = PageRequest.of(pageNo, pageSize);// 通常使用 Specification 的匿名內部類Specification<Card> specification = new Specification<Card>() {@Overridepublic Predicate toPredicate(Root<Card> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Path path = root.get("id");// gt 是大于的意思。這里代表 id 大于 2Predicate predicate1 = cb.gt(path, 2);// equal 是等于的意思,代表查詢 num 值為 422803 的數據記錄Predicate predicate2 = cb.equal(root.get("num"), 422803);// 構建組合的 PredicatePredicate predicate = cb.and(predicate1, predicate2); return predicate;}};Page<Card> page = cardRepository.findAll(specification, pageable);System.out.println("總記錄數: " + page.getTotalElements());System.out.println("當前第: " + (page.getNumber() + 1) + "頁");System.out.println("總頁數: " + page.getTotalPages());System.out.println("當前頁面的 List: " + page.getContent());System.out.println("當前頁面的記錄數: "+ page.getNumberOfElements());}
)

代碼解釋如下:

  • CriteriaQuery 接口:specific 的頂層查詢對象,它包含查詢的各個部分,比如,selectfromwheregroup byorder by 等。CriteriaQuery 對象只對實體類型或嵌入式類型的 Criteria 查詢起作用。
  • root:代表查詢的實體類是 Criteria 查詢的根對象。Criteria 查詢的根定義了實體類型,能為將來的導航獲得想要的結果。它與 SQL 查詢中的 From 子句類似。Root 實例是類型化的, 且規定了 From 子句中能夠出現的類型。查詢根實例通過傳入一個實體類型給 AbstractQuery.from 方法獲得。
  • query:可以從中得到 Root 對象,即告知 JPA Criteria 查詢要查詢哪一個實體類。還可以添加查詢條件,并結合 EntityManager 對象得到最終查詢的 TypedQuery 對象。
  • CriteriaBuilder 對象:用于創建 Criteria 相關對象的工廠,可以從中獲取到 Predicate 對象。
  • Predicate 類型:代表一個查詢條件。

運行上面的測試代碼,在控制臺會輸出如下結果(確保數據庫已經存在數據):

Hibernate: select card0_.id as id1_0_, card0_.num as num2_0_ from card cardO_ where card0_.id>2 and card0_.num=422803 limit ?
Hibernate: select count(card0_.id) as col_0_0_ from card card0_ where card0_.id>2 and card0_.num=422803
總記錄數: 6
當前第: 1頁 
總頁數: 2 
當前頁面的 List: [Card(id=4, num=422803), Card(id=8, num=422803), Card(id=10, num=422803), Card(id=20, num=422803), Card(id=23, num=422803)] 
當前頁面的記錄數: 5

5.用 ExampleMatcher 進行查詢

Spring Data 可以通過 Example 對象來構造 JPQL 查詢,具體用法見以下代碼:

User user = new User();
//構建查詢條件
user.setName("pipi")ExampleMatcher matcher = ExampleMatcher.matching()// 創建一個 ExampleMatcher, 不區分大小寫匹配 name.withIgnorePaths("name")// 包括 null 值.withIncludeNullValues()// 執行后綴匹配.withStringMatcherEnding();
// 通過 Example 構建查詢
Example<User> example = Example.of(user, matcher);
List<User> list = userRepository.findALL(example);

默認情況下,ExampleMatcher 會匹配所有字段。

可以指定單個屬性的行為(如 name 或內嵌屬性 name.user)。如:

  • withMatcher("name", endsWith())
  • withMatcher("name", startsWith().ignoreCase())

6.用謂語 QueryDSL 進行查詢

QueryDSL 也是基于各種 ORM 之上的一個通用查詢框架,它與 Spring Data JPA 是同級別的。使用 QueryDSL 的 API 可以寫出 SQL 語句(Java 代碼,非真正標準 SQL),不需要懂 SQL 語句。它能夠構建類型安全的查詢。這與 JPA 使用原生查詢時有很大的不同,可以不必再對 Object[] 進行操作。它還可以和 JPA 聯合使用。

7.用 NamedQuery 進行查詢

官方不推薦使用 NamedQuery,因為它的代碼必須寫在實體類上面,這樣不夠獨立。其使用方法見以下代碼:

?Entity 
@NamedQuery(name = "User.findByName", query = "select u from User u where u.name = ?1") 
public class User {
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/38796.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/38796.shtml
英文地址,請注明出處:http://en.pswp.cn/web/38796.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mac視頻下載工具,兼容14系統,Downie 4軟件下載

Downie 4 是一款由James Application開發的視頻下載軟件&#xff0c;支持Mac操作系統。該軟件允許用戶從各種視頻網站上下載視頻內容&#xff0c;以便于在本地設備上觀看&#xff0c;無需依賴互聯網連接。自動下載&#xff1a;可以設置Downie 4自動下載指定網站上的視頻&#x…

當+=的時候,為什么會出現NaN?

問: var textToDisplay; // "testing"; textToDisplay "testing"; textToDisplay 1; var someNumber 1; var oneMoreNumber; oneMoreNumber textToDisplay someNumber; //results in NaN console.log(oneMoreNumber); 這里的結果是NaN? 回答: 是…

【LinuxC語言】線程池的原理和實現

文章目錄 前言為什么需要線程池線程池的原理總結前言 在現代計算中,多線程編程已經成為一種常見的做法,它可以幫助我們更有效地利用多核處理器的能力。然而,頻繁地創建和銷毀線程會帶來一定的開銷。為了解決這個問題,我們可以使用一種稱為“線程池”的技術。線程池是一種在…

黑馬點評-Redis的緩存擊穿,緩存雪崩,緩存穿透,互斥鎖,邏輯過期

文章目錄 1.緩存穿透2.緩存雪崩3.緩存擊穿3.1 互斥鎖3.2 基于邏輯過期 1.緩存穿透 解決辦法 寫入NULL值到Redis緩存&#xff0c;以后就會命中Redis的控制緩存而不會出現請求直接打到數據庫的問題&#xff01; 代碼 2.緩存雪崩 這個概念很好理解&#xff0c;雪崩就是無數的…

【LLM大模型書】從零開始大模型開發與微調:基于PyTorch與ChatGLM (附PDF)

今天又來給大家推薦一本大模型方面的書籍<從零開始大模型開發與微調&#xff1a;基于PyTorch與ChatGLM>。 本書使用PyTorch 2.0作為學習大模型的基本框架&#xff0c;以ChatGLM為例詳細講解大模型的基本理論、算法、程序實現、應用實戰以及微調技術&#xff0c;為讀者揭…

設備樹在Linux系統的屬性

設備樹源文件 設備樹源文件擴展名為.dts&#xff0c;我們在前面移植 Linux 的時候卻一直在使用.dtb 文件&#xff0c;那么 DTS 和 DTB 這兩個文件是什么關系呢&#xff1f; DTS 是設備樹源碼文件&#xff0c; DTB 是將 DTS 編譯以后得到的二進制文件。將.dts 編譯為.dtb 需要什…

【微信小程序開發實戰項目】——如何制作一個屬于自己的花店微信小程序(2)

&#x1f468;?&#x1f4bb;個人主頁&#xff1a;開發者-曼億點 &#x1f468;?&#x1f4bb; hallo 歡迎 點贊&#x1f44d; 收藏? 留言&#x1f4dd; 加關注?! &#x1f468;?&#x1f4bb; 本文由 曼億點 原創 &#x1f468;?&#x1f4bb; 收錄于專欄&#xff1a…

FreeRTOS和UCOS操作系統使用筆記

FreeRTOS使用示例 UCOS使用示例 信號量使用 信號量訪問共享資源區/ OS_SEMMY_SEM; //定義一個信號量&#xff0c;用于訪問共享資源OSSemCreate ((OS_SEM* )&MY_SEM, //創建信號量&#xff0c;指向信號量(CPU_CHAR* )"MY_SEM", //信號量名字(OS_SEM_CTR )1, …

軟件模型分類及特點

在軟件開發的世界里&#xff0c;我們經常會遇到業務模型、系統模型和軟件模型這三個層次。這些模型各有特點&#xff0c;相互之間也有著緊密的聯系。通過理解這三個層次之間的映射關系&#xff0c;我們能更好地理解和掌握軟件開發的全過程 1. 業務模型 業務模型描述了組織的業…

政務單位網站SSL證書選擇策略

在數字化快速發展的今天&#xff0c;政務單位網站作為政府與公眾溝通的重要橋梁&#xff0c;其安全性和可信度顯得尤為重要。SSL證書作為保障網站安全的重要手段&#xff0c;其選擇對于政務單位網站來說至關重要。本文將探討政務單位網站在選擇SSL證書時應該考慮的因素&#xf…

如何使用python網絡爬蟲批量獲取公共資源數據教程?

原文鏈接&#xff1a;如何使用python網絡爬蟲批量獲取公共資源數據教程&#xff1f;https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247608240&idx4&snef281f66727afabfaae2066c6e92f792&chksmfa826657cdf5ef41571115328a09b9d34367d8b11415d5a5781dc4c…

【AI提升】如何使用大模型:本機離線和FastAPI服務調用

大模型本身提供的功能&#xff0c;類似于windows中的一個exe小工具&#xff0c;我們可以本機離線調用然后完成具體的功能&#xff0c;但是別的機器需要訪問這個exe是不可行的。常見的做法就是用web容器封裝起來&#xff0c;提供一個http接口&#xff0c;然后接口在后端調用這個…

KV260視覺AI套件--PYNQ-DPU-Resnet50

目錄 1. 簡介 2. 代碼解析 3. 全部代碼展示 4. 總結 1. 簡介 本文以 Resnet50 為例&#xff0c;展示使用 PYNQ 調用 DPU 運行 Resnet50 網絡的詳細過程&#xff0c;并對其中關鍵代碼做出解釋。 PYNQ是一個針對Xilinx Zynq平臺的Python開發框架&#xff0c;它允許開發者使…

KEYSIGHT是德科技 E5063A ENA 系列網絡分析儀

E5063A ENA 矢量網絡分析儀 18GHz 2端口 降低無源射頻元器件的測試成本 Keysight E5063A ENA 是一款經濟適用的臺式矢量網絡分析儀&#xff0c;可用于測試簡單的無源元器件&#xff0c;例如頻率最高達到 18 GHz 的天線、濾波器、電纜或連接器。 作為業界聞名的 ENA 系列…

深入解析 Laravel 事件系統:架構、實現與應用

Laravel 的事件系統是框架中一個強大且靈活的功能&#xff0c;它允許開發者在應用程序中定義和使用自定義事件和監聽器。這個系統基于觀察者模式&#xff0c;使得代碼解耦和可維護性大大提高。在本文中&#xff0c;我們將深入探討 Laravel 事件系統的工作原理、如何實現自定義事…

python @裝飾器的用法

裝飾器&#xff08;decorators&#xff09;是 Python 中的一種高級特性&#xff0c;它允許開發者修改函數或方法的行為&#xff0c;而不改變其定義。裝飾器通常用于日志記錄、權限檢查、性能測量等場景。裝飾器是通過在函數定義的前一行加上 decorator_name 來使用的。 基本用…

Qt簡單文本查找

Qt版本&#xff1a; Qt6 具體代碼&#xff1a; 1. 頭文件 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>class QLineEdit; class QDialog; class QPushButton; class QVBoxLayout; class QTextEdit;QT_BEGIN_NAMESPACE namespace Ui…

為什么AI算法工程師要求C++?

在開始前剛好我有一些資料&#xff0c;是我根據網友給的問題精心整理了一份「c&#xff0b;&#xff0b;的資料從專業入門到高級教程」&#xff0c; 點個關注在評論區回復“666”之后私信回復“666”&#xff0c;全部無償共享給大家&#xff01;&#xff01;&#xff01;能跑出…

找到字符串中所有子串出現的位置python

直接find干就完了。 如果你希望找到字符串中所有子串出現的位置&#xff0c;而不僅僅是一個位置&#xff0c;你可以通過循環查找并收集所有起始位置。以下是修改后的代碼&#xff1a; def find_all_substring_positions(string, substring): positions [] # 用于存儲所有…

與枚舉結合的策略模式

枚舉類&#xff1a; package com.dtranx.tools.corpora.businessapi.enums;import com.dtranx.tools.commons.vo.EnumResponseVo; import com.google.common.collect.Lists;import java.util.List;/*** ClassName SimpleSearchMode* Description TODO* Date 2024/5/28 15:55* A…