這邊來認識一些我們可能會用到的一些資料庫查詢操作
根據前面的 products 結構來插入一些資料熟悉一些操作的用法吧。
1 2 3 4 5 6 7 8 9 10 11 12
| 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
1 2 3 4 5
| @GetMapping("/q") public Product getProductsByName(@RequestParam String name) { return productService.getProductByName(name); }
|
service
1 2 3 4 5 6 7 8 9 10 11
| @Service public class ProductService { @Autowired private ProductRepository productRepository;
public Product getProductByName(String name) { return productRepository.findByName(name); } }
|
repository
1 2 3
| public interface ProductRepository extends JpaRepository<Product, Integer> { Product findByName(String name); }
|
(二) 範圍條件
可以根據數值的範圍來進行查詢,像是這邊可以用價錢來進行示範
他的格式會像 findBy{判斷欄位}GreaterThanEqual()
- 大於
findByPriceGreaterThan()
- 大於等於
findByPriceGreaterThanEqual()
- 小於
findByPriceLessThan()
- 小於等於
findByPriceLessThanEqual()
這邊用大於等於
controller
1 2 3 4
| @GetMapping("/priceGreaterThanEqual") public List<Product> getProductsByPriceGreaterThanEqual(@RequestParam int range) { return productService.getProductGreaterThanEqual(range); }
|
service
1 2 3 4 5 6 7 8 9 10
| @Service public class ProductService { @Autowired private ProductRepository productRepository;
public List<Product> getProductGreaterThanEqual(int range) { return productRepository.findByPriceGreaterThanEqual(range); }
}
|
repository
1 2 3 4 5
| @Repository public interface ProductRepository extends JpaRepository<Product, Integer> { Product findByName(String name); List<Product> findByPriceGreaterThanEqual(int range); }
|
查詢大於 60 元剛好只有 69.99 元的最終幻想符合
多個條件
可透過 And 或 Or 組合
controller
1 2 3 4 5
| @GetMapping("/nameOrPrice") public List<Product> getProductsByNameOrPrice(@RequestParam String name, @RequestParam double price) { return productService.getProductByNameOrPrice(name, price); }
|
service
1 2 3
| public List<Product> getProductByNameOrPrice(String name, double price) { return productRepository.findByNameOrPrice(name, price); }
|
repository
1 2 3 4 5
| @Repository public interface ProductRepository extends JpaRepository<Product, Integer> { List<Product> findByNameOrPrice(String name, double price); }
|
or 的話只要其中一項條件符合就會執行,像是下面有搜出 name = 黑帝斯 也有搜出 price = 49.99
原生 SQL
使用 JPA 如果不夠彈性你也可使用原生的語法 @Query
@Query 裡面要第一個參數註明是 nativeQuery = true
, 第二個參數是 vlaue = “{sql 語法}” ,也可以把 value 省略,直接用 SQL 字串放第二個參數,注意這邊 SQL 語法結尾請不要加分號 “;”
參數的帶入也可以用 :param 的方式,這邊其實寫法有很多種,大家就找到自己喜歡或是團隊易懂的方式來撰寫。
*如果 nativeQuery 沒有開啟就是使用 JPQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
@Query("SELECT p FROM Product p WHERE p.name = :name OR p.price = :price")
@Query( nativeQuery = true, value = "SELECT * FROM products WHERE name = ?1 OR price = ?2" ) List<Product> findByNameOrPriceNative(String name, double price);
|
Sort 物件
利用 Sort 物件可以做到排序,看是要升序(ASC)或是降序(DESC),這個物件是可以直接帶入 repository 的方法中告知 JPA 要進行排序
1 2 3 4
| Sort sort = Sort.by({欄位}).ascending()
Sort sort = Sort.by({欄位}).descending();
|
以撈出全部資料 Service 方法為例,根據價錢進行升序
1 2 3 4
| public List<Product> getAllProducts() { Sort sort = Sort.by("price").ascending(); return productRepository.findAll(sort); }
|
可以看到顯示資料就照價錢由小到大排了
Sort 也可以整合下面分頁物件一起做到排序及分頁
Pageable 物件
Pageabe 是一個介面,通常會放入三個參數來透過 PageRequest 方法實作
- 第一個參數 page 表示第幾頁(需要特別注意第一頁是 0)
- 第二個參數 limit 表示回傳資料筆數上限
- 第三個參數 sort 表示排序物件
1
| Pageable pageable = PageRequest.of(page, limit, sort);
|
把上面的 Sort 物件一起帶進去,並且告知我要取得第一頁的 3 筆資料
1 2 3 4 5 6 7 8 9
| 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 筆資料
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| { "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。那下篇來講一些關於資料庫關聯的一些操作介紹吧。
參考資料: