這邊來認識一些我們可能會用到的一些資料庫查詢操作
根據前面的 products 結構來插入一些資料熟悉一些操作的用法吧。
INSERT INTO products (name, price, description) VALUES
('薩爾達傳說:曠野之息', 59.99, '設定在幻想世界中的開放世界動作冒險遊戲。'),
('超級瑪利歐:奧德賽', 49.99, '以瑪利歐為主角的平臺遊戲,探索各種世界。'),
('集合啦!動物森友會', 54.99, '在無人島上進行發展的生活模擬遊戲。'),
('最終幻想 VII 重製版', 69.99, '經典 RPG 的重製版,具有更新的圖像和遊戲玩法。'),
('巫師3:狂獵', 39.99, '開放世界 RPG,玩家扮演狩魔獵人傑洛特。'),
('電馭叛客2077', 59.99, '設定在反烏托邦未來世界的開放世界 RPG。'),
('對馬戰鬼', 59.99, '設定在日本封建時代的動作冒險遊戲。'),
('碧血狂殺2', 49.99, '以西部為主題的開放世界動作冒險遊戲。'),
('黑帝斯', 24.99, '在地下城中進行逃脫的類 Roguelike 遊戲。'),
('我們之中', 4.99, '在太空船上進行的多人派對遊戲,涉及團隊合作與背叛。');
前面一篇有提到可以直接透過欄位名稱來查找,JPA會自動幫我們對應,最常用到的就是 findById,如果想要查找其他欄位就可以直接改成像是 findByName, findByPrice 等等都可以讓 JPA 幫我們匹配。
這邊根據 findByName 我們可以透過名稱找到對應商品
controller
@GetMapping("/q")
public Product getProductsByName(@RequestParam String name) {
return productService.getProductByName(name);
}
service
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public Product getProductByName(String name) {
return productRepository.findByName(name);
}
}
repository
public interface ProductRepository extends JpaRepository<Product, Integer> {
Product findByName(String name);
}
可以根據數值的範圍來進行查詢,像是這邊可以用價錢來進行示範
他的格式會像 findBy{判斷欄位}GreaterThanEqual()
findByPriceGreaterThan()
findByPriceGreaterThanEqual()
findByPriceLessThan()
findByPriceLessThanEqual()
這邊用大於等於
controller
@GetMapping("/priceGreaterThanEqual")
public List<Product> getProductsByPriceGreaterThanEqual(@RequestParam int range) {
return productService.getProductGreaterThanEqual(range);
}
service
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public List<Product> getProductGreaterThanEqual(int range) {
return productRepository.findByPriceGreaterThanEqual(range);
}
}
repository
@Repository
public interface ProductRepository extends JpaRepository<Product, Integer> {
Product findByName(String name);
List<Product> findByPriceGreaterThanEqual(int range);
}
查詢大於 60 元剛好只有 69.99 元的最終幻想符合
可透過 And 或 Or 組合
controller
@GetMapping("/nameOrPrice")
public List<Product> getProductsByNameOrPrice(@RequestParam String name, @RequestParam double price) {
return productService.getProductByNameOrPrice(name, price);
}
service
public List<Product> getProductByNameOrPrice(String name, double price) {
return productRepository.findByNameOrPrice(name, price);
}
repository
@Repository
public interface ProductRepository extends JpaRepository<Product, Integer> {
List<Product> findByNameOrPrice(String name, double price);
}
or 的話只要其中一項條件符合就會執行,像是下面有搜出 name = 黑帝斯 也有搜出 price = 49.99
使用 JPA 如果不夠彈性你也可使用原生的語法 @Query
@Query 裡面要第一個參數註明是 nativeQuery = true
, 第二個參數是 vlaue = “{sql 語法}” ,也可以把 value 省略,直接用 SQL 字串放第二個參數,注意這邊 SQL 語法結尾請不要加分號 “;”
參數的帶入也可以用 :param 的方式,這邊其實寫法有很多種,大家就找到自己喜歡或是團隊易懂的方式來撰寫。
*如果 nativeQuery 沒有開啟就是使用 JPQL
// 用 """ """ 可以不用顧慮換行問題
// @Query(
// nativeQuery = true,
// value = """
// SELECT *
// FROM `products`
// WHERE `name` = ?1 OR `price` = ?2
// """
// )
// JPQL 須注意如果語法長中間可能換行及空格導致語法錯誤
@Query("SELECT p FROM Product p WHERE p.name = :name OR p.price = :price")
// Native SQL 須注意如果語法長中間可能換行及空格導致語法錯誤
@Query(
nativeQuery = true,
value = "SELECT * FROM products WHERE name = ?1 OR price = ?2"
)
List<Product> findByNameOrPriceNative(String name, double price);
利用 Sort 物件可以做到排序,看是要升序(ASC)或是降序(DESC),這個物件是可以直接帶入 repository 的方法中告知 JPA 要進行排序
// asc
Sort sort = Sort.by({欄位}).ascending()
// desc
Sort sort = Sort.by({欄位}).descending();
以撈出全部資料 Service 方法為例,根據價錢進行升序
public List<Product> getAllProducts() {
Sort sort = Sort.by("price").ascending();
return productRepository.findAll(sort);
}
可以看到顯示資料就照價錢由小到大排了
Sort 也可以整合下面分頁物件一起做到排序及分頁
Pageabe 是一個介面,通常會放入三個參數來透過 PageRequest 方法實作
Pageable pageable = PageRequest.of(page, limit, sort);
把上面的 Sort 物件一起帶進去,並且告知我要取得第一頁的 3 筆資料
public Page<Product> getAllProducts() {
Sort sort = Sort.by("price").ascending();
Pageable pageable = PageRequest.of(0,3, sort);
Page<Product> productPage = productRepository.findAll(pageable);
return productPage;
}
回傳的資料可以看到確實有排序,還有提供分頁的相關資訊,也只顯示出第一頁的 3 筆資料
{
"content": [
{
"id": 4,
"name": "最終幻想 VII 重製版",
"price": 69.99,
"description": "經典 RPG 的重製版,具有更新的圖像和遊戲玩法。"
},
{
"id": 1,
"name": "薩爾達傳說:曠野之息",
"price": 59.99,
"description": "設定在幻想世界中的開放世界動作冒險遊戲。"
},
{
"id": 6,
"name": "電馭叛客2077",
"price": 59.99,
"description": "設定在反烏托邦未來世界的開放世界 RPG。"
}
],
"pageable": {
"pageNumber": 0,
"pageSize": 3,
"sort": {
"empty": false,
"sorted": true,
"unsorted": false
},
"offset": 0,
"paged": true,
"unpaged": false
},
"totalPages": 4,
"totalElements": 10,
"last": false,
"size": 3,
"number": 0,
"sort": {
"empty": false,
"sorted": true,
"unsorted": false
},
"numberOfElements": 3,
"first": true,
"empty": false
}
以上就是基本的一些查詢跟應用,對於許多網站的搜尋及資料的查找都是相當基本的用法,Spring Data Jpa 也提供給我們許多方便的用法,還有一定的彈性可以自行撰寫原生 SQL。那下篇來講一些關於資料庫關聯的一些操作介紹吧。
Ref:
相關文章也會同步更新我的部落格,有興趣也可以在裡面找其他的技術分享跟資訊。