iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0
Software Development

Spring Boot 零基礎入門系列 第 26

Spring Boot 零基礎入門 (26) - Spring JDBC 的用法(上)- 執行 INSERT、UPDATE、DELETE SQL

  • 分享至 

  • xImage
  •  

個人網站好讀版:Spring Boot 零基礎入門 系列文章

哈囉大家好,我是古古。

在上一篇文章中,我們有在 Spring Boot 中載入了 Spring JDBC 的功能,並且也有設定好了 MySQL 資料庫的連線資訊。

那麼接著這篇文章,我們就會正式來介紹,要如何使用 Spring JDBC 的功能,在 Spring Boot 程式中執行 SQL 語法,進而去操作資料庫內部的數據。

Spring JDBC 用法介紹


在 Spring JDBC 中,會根據 SQL 語法區分成兩大類,分別是「update 系列」和「query 系列」。

  • 在 update 系列的方法中,可以執行 INSERT、UPDATE、DELETE 這三種 SQL 語法
  • 而在 query 系列的方法中,只能執行 SELECT 這一種 SQL 語法

26-1.png

因此大家如果想要執行的是 INSERT SQL,那就是得使用 update() 方法來執行,而如果想執行的是 SELECT SQL 的話,則是得改用 query() 方法來執行。

也因為 update()query() 這兩個方法在用法上會有點差別,因此接下來我們就會分成上、下兩篇文章,分別來介紹這兩種方法的用法。

因此在這篇文章中,我們就會先來介紹 update() 的用法。

補充:怎麼背哪種 SQL 語法用哪個方法來執行?

因為在 Spring JDBC 中,INSERT、UPDATE、DELETE 這三種 SQL 語法,必須要用 update() 方法來執行,而 SELECT 這一種 SQL 語法,則是得改用 query() 方法來執行,所以大家一開始接觸的時候,可能會怕自己忘記哪種 SQL 語法要用哪個方法來執行。

不過這個對應關係其實是不用特別背的!因為我們可以透過「方法的名稱」,去推敲出當下這個 SQL 語法要用哪種方法來執行。

舉例來說,像是 update() 方法代表的是「更新資料庫中的數據」的意思,所以在 INSERT、UPDATE、DELETE 這三種情境中,都是廣義的表達「改變資料庫中儲存的數據」的含義。

  • INSERT:在資料庫中「新增」一筆數據
  • UPDATE:在資料庫中「修改」一筆已存在的數據
  • DELETE:在資料庫中「刪除」一筆數據

因此對於 INSERT、UPDATE、DELETE 這三種 SQL 語法,就都可以使用 update() 方法來執行。

而同樣的道理,因為另一個 query() 方法代表的是「查詢資料庫中的數據」的意思,所以他就會去對應到 SELECT 這一種 SQL 語法,專門去查詢資料庫中的數據。因此針對 SELECT SQL,就是只能使用 query() 方法來執行。

所以大家以後在使用 Spring JDBC 時,就不用特別背誦哪種 SQL 要用哪一個方法來執行,只要直接從方法名稱上去推敲就可以了!

update() 的基本用法


大概了解了 update()query() 方法之間的差別之後,接著我們就可以來詳細介紹一下,要如何使用 update() 方法去執行 INSERT、UPDATE、DELETE 這三種 SQL 語法。

要使用 update() 方法去執行 INSERT、UPDATE、DELETE 這三種 SQL 語法的話,可以分成四個步驟來實作:

步驟一:注入 NamedParameterJdbcTemplate Bean

使用 update() 的第一步,就是要先在你的 Bean 裡面,去注入 NamedParameterJdbcTemplate 進來。

因此我們就可以在 StudentController 中,先使用 @Autowired,去注入 NamedParameterJdbcTemplate 這個 Bean 進來(如下圖中的第 14~15 行所示)。

@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

26-2.png

而我們之所以可以直接在 StudentController 中去注入 NamedParameterJdbcTemplate 這個 Bean,就是因為這個 Bean 是由 Spring JDBC 自動幫我們生成的 Bean,他會負責去處理和資料庫溝通的所有事項,因此後續我們就可以透過 NamedParameterJdbcTemplate,去執行想要執行的 SQL 語法了。

所以簡單來說,當我們在使用 Spring JDBC 的功能時,其實很大部分的時間都是在和 NamedParameterJdbcTemplate 打交道,即是學習要如何使用 NamedParameterJdbcTemplate 中所提供的 update()query() 方法,去執行我們想執行的 SQL 語法。

步驟二:撰寫 SQL 語法

在 StudentController 中注入好 NamedParameterJdbcTemplate 進來之後,接著第二步,就是去寫出我們想要執行的 SQL 語法。

所以我們可以先在 StudentController 中創建一個 String 類型的變數 sql,並且在裡面寫上我們想要執行的 SQL 語法(如下圖中的第 20 行所示)。

舉例來說,下方就是將一條 INSERT SQL 的語句,儲存在 sql 的變數裡面,而這條 INSERT SQL 的用途,就是「在 student table 中插入一筆 id 為 3、並且 name 為 John」的數據。因此到時候當 Spring JDBC 去執行這條 SQL 時,就會在 student table 中插入 John 這筆新數據。

String sql = "INSERT INTO student(id, name) VALUES (3, 'John')";

26-3.png

步驟三:新增一個 Map<String, object> 的 map 變數

撰寫完想要執行的 SQL 語句之後,接著第三步,就是去新增一個類型為 Map<String, object> 的 map 變數出來。

因此就可以在 StudentController 中添加下方的程式(如下圖中的第 22 行所示):

Map<String, Object> map = new HashMap<>();

26-4.png

補充:我們後續就會介紹這個 map 變數的用途了,因此目前就先照抄即可。

步驟四:使用 update() 方法

當前面的步驟都完成之後,最後要做的第四部,就是去使用 namedParameterJdbcTemplate 中的 update() 方法,並且把上面所宣告的 sql 和 map 這兩個變數,依照順序傳進去 update() 方法裡面(如下圖中的第 24 行所示)。

namedParameterJdbcTemplate.update(sql, map);

26-5.png

只要完成了這四個步驟,我們就完成了 Spring JDBC 的實作了!

因此到時候當 Spring Boot 執行到第 24 行的 update() 方法時,就會去執行我們所指定的 SQL 語法(即是執行 sql 變數中所儲存的 SQL 語法,INSERT INTO student(id, name) VALUES (3, 'John')),所以最終 Spring Boot 就可以成功的在 student table 中,插入這筆 John 的新數據了!

實際測試

完成上述的程式之後,我們可以來運行這個 Spring Boot 程式,測試一下他的效果。

成功運行 Spring Boot 程式之後,接著就回到 API Tester 中,並且填入以下的請求參數:

26-6.png

填寫完畢之後,接著按下右側的 Send 鍵,就可以去發起一個 Http 請求。

而在請求成功之後,就可以回到 IntelliJ 上,然後點開右側的資料庫圖示,並且開啟 student table。

26-7.png

這時在 student table 中,就可以看到多出了一筆「id 為 3、並且 name 為 John」的數據。

26-8.png

所以這就表示,我們就成功的透過了 Spring JDBC 的 update() 方法,在 Spring Boot 中執行 INSERT SQL 的語法,進而新增一筆數據到資料庫中了!

而在我們練習完 update() 方法的基本用法之後,接下來我們也可以來介紹一下,前面我們所創建的 Map<String, object> map 變數,他的用途為何。

update() 中的 map 參數用法


在上面的「步驟三:新增一個 Map<String, object> 的 map 變數」小節裡,我們當時有先創建了一個 map 變數(下圖中的第 22 行),並且當時告訴大家先照抄就好,不過現在我們就可以回頭來介紹這個 map 變數的用法了。

26-9.png

這個 map 變數的用途,是用來「放置 SQL 語法中的變數的值」,這句話聽起來可能有點抽象,所以我們可以直接透過一個例子,來了解一下 map 變數的用法為何。

例子:根據前端的參數,動態的決定 SQL 中的值

在上面那段程式中,我們是直接寫死一條 SQL 語法 INSERT INTO student (id, name) VALUES (3, 'John') 在程式裡面,因此不管前端傳了什麼參數過來,我們始終都只能夠在資料庫中,去新增一筆「id 為 3、並且 name 為 John」的數據。

不過這樣子的寫法非常的不彈性,如果我們想要改成是去新增一筆「id 為 4、name 為 Bob」的數據的話,那麼就得先停止 Spring Boot 程式,修改這一行 SQL 語法,然後再重新運行 Spring Boot 程式,在實作上就會變得非常麻煩。

因此,假設我們想要「動態的決定」當前 SQL 語法中的值的話,那就需要依靠 map 這個變數來幫忙了!

前置準備

為了練習 map 變數的用途,首先我們得先做一些前置準備,去接住前端傳過來的參數。

因此大家可以先創建一個 Student class,並且在裡面創建兩個變數 id 和 name,程式如下:

public class Student {

    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

接著在 StudentController 裡,在第 19 行的 insert() 方法的實作中,添加 @RequestBody 註解,後續就可以使用 @RequestBody 去接住前端傳過來的參數。

26-10.png

補充:不熟悉 @RequsetBody 的用法的話,可以回頭參考 Day 19 - 取得請求參數(上)- @RequestParam、@RequestBody 的介紹。

修改 SQL 語法、添加 map 變數中的值

使用了 @RequestBody 接住前端傳來的變數之後,接著我們就可以將前端傳過來的 id 和 name 的值,去放到 map 變數裡面,這樣後續就可以插入這筆新的數據到資料庫中了。

因此此處有兩個地方需要修改:

首先是第 19 行的 SQL 語法,要將 (3, John) 的程式,改寫成 (:studentId, :studentName)

String sql = "INSERT INTO student(id, name) VALUES (:studentId, :studentName)";

接著需要在 map 變數下方,添加第 24、25 行的程式,也就是在 map 變數中新增兩組 key-value 的值。

map.put("studentId", student.getId());
map.put("studentName", student.getName());

26-11.png

在這些改動中,首先我們先將 SQL 語法從 (3, John) 改寫成是 (:studentId, :studentName)而只要在 SQL 語法中加上了「:」,就表示這是一個「SQL 中的變數」。

舉例來說,像是 :studentId,就表示我們指定這是一個 SQL 中的變數,名字叫做 studentId。

至於後面的 :studentName,就是表示我們指定另一個 SQL 中的變數,名字叫做 studentName。

因此我們就可以透過這個邏輯,在同一句 SQL 語法裡面,添加無數個 SQL 中的變數了。

26-12.png

而在 SQL 語法中的 :studentId:studentName 這些變數,我們後續就可以使用第 23 行的 map,來指定這些變數的值為多少。因此在使用 map 變數時,前面要放的是「SQL 變數的名字」,後面放的則是「這個 SQL 變數的值是多少」。

舉例來說,假設我們想要指定 :studentId 的值為 5 的話,那麼就可以寫成:

map.put("studentId", 5);

如果我們想要指定 :studentId 的值為「前端傳過來的 id 的值」的話,那麼就可以寫成是:

map.put("studentId", student.getId());

因此透過 map 變數,我們就可以動態的去決定 SQL 中的變數的值,進而實作出「動態的決定要插入的數據為何」的效果了!

26-13.png

補充:如果看到這裡仍舊覺得思緒有點亂、不太了解 map 的具體用法的話,建議可以先直接往下看後面的「實際測試」的部分,實際的用 API Tester 和 Spring Boot 程式來搭配練習,慢慢的就能夠掌握 map 的用法了。

實際測試

完成上述的程式之後,需要先重新運行一下 Spring Boot 程式,等到重新運行成功之後,再回到 API Tester 中進行後面的測試。

在 API Tester 中,我們要修改 request body 的部分,改成填入以下的參數,表示要插入一筆「id 為 4、 name 為 Bob」的數據到資料庫。

26-14.png

修改好之後,就按下右邊的 Send 鍵,去發出一個 Http 請求。在請求成功之後,就可以回到 IntelliJ 上,然後開啟右邊側邊欄中的 student table 查看一下數據。

26-15.png

這時候在 student table 中,就可以看到多出了一筆「id 為 4、並且 name 為 Bob」的數據。

26-16.png

因此這就表示,我們就成功的透過了 update() 方法的 map 參數,動態的去決定 SQL 語法中的變數了!所以後續我們就可以根據前端所傳遞過來的參數,動態的在資料庫中插入不同的數據了,這也是實務上非常常見的作法,建議大家也可以多練習幾次,加深這邊的實作印象。

update() 方法的用法總結


所以總結上述的介紹,如果想要使用 update() 方法,在 Spring Boot 中執行 INSERT、UPDATE、
DELETE 這三種 SQL 語法的話,那麼就只要在 update() 方法中,按照順序填入以下兩個參數:

  • sql 參數: 放想要執行的 SQL 語法
  • map 參數: 動態的決定 SQL 變數中的值

26-17.png

這樣子就可以在 Spring Boot 中,去執行你想要執行的 INSERT、UPDATE、DELETE 的 SQL 語法了!

總結


在這篇文章中,我們先去介紹了 Spring JDBC 中的 update() 的基本用法,並且也有深入介紹 update() 中的 map 參數用法,因此大家以後就可以透過這個寫法,在 Spring Boot 程式中去執行 INSERT、UPDATE、DELETE 這三種 SQL 語法了。

那麼下一篇文章,我們就會接著來介紹 Spring JDBC 中的另一個核心方法,也就是 query() 方法,那我們就下一篇文章見啦!

補充:本文是擷取自我開設的線上課程 Java 工程師必備!Spring Boot 零基礎入門 的內容,如果你想了解更多的 Spring Boot 的用法,歡迎參考課程簡介。


上一篇
Spring Boot 零基礎入門 (25) - 資料庫連線設定、IntelliJ 資料庫管理工具介紹
下一篇
Spring Boot 零基礎入門 (27) - Spring JDBC 的用法(下)- 執行 SELECT SQL
系列文
Spring Boot 零基礎入門30
.

尚未有邦友留言

立即登入留言