使用JDBC操作數據庫的時候,經常會執行一些批量操作。
例如,一次性給會員增加可用優惠券若干,我們可以執行以下SQL代碼:
~~~
INSERT INTO coupons (user_id, type, expires) VALUES (123, 'DISCOUNT', '2030-12-31');
INSERT INTO coupons (user_id, type, expires) VALUES (234, 'DISCOUNT', '2030-12-31');
INSERT INTO coupons (user_id, type, expires) VALUES (345, 'DISCOUNT', '2030-12-31');
INSERT INTO coupons (user_id, type, expires) VALUES (456, 'DISCOUNT', '2030-12-31');
...
~~~
實際上執行JDBC時,因為只有占位符參數不同,所以SQL實際上是一樣的:
<br>
~~~
for (var params : paramsList) {
PreparedStatement ps = conn.preparedStatement("INSERT INTO coupons (user_id, type, expires) VALUES (?,?,?)");
ps.setLong(params.get(0));
ps.setString(params.get(1));
ps.setString(params.get(2));
ps.executeUpdate();
}
~~~
類似的還有,給每個員工薪水增加10%~30%:
~~~
UPDATE employees SET salary = salary * ? WHERE id = ?
~~~
<br>
<br>
通過一個循環來執行每個`PreparedStatement`雖然可行,但是性能很低。SQL數據庫對SQL語句相同,但只有參數不同的若干語句可以作為batch執行,即批量執行,這種操作有特別優化,速度遠遠快于循環執行每個SQL。
在JDBC代碼中,我們可以利用SQL數據庫的這一特性,把同一個SQL但參數不同的若干次操作合并為一個batch執行。我們以批量插入為例,示例代碼如下:
```
try (PreparedStatement ps = conn.prepareStatement("INSERT INTO students (name, gender, grade, score) VALUES (?, ?, ?, ?)")) {
// 對同一個PreparedStatement反復設置參數并調用addBatch():
for (Student s : students) {
ps.setString(1, s.name);
ps.setBoolean(2, s.gender);
ps.setInt(3, s.grade);
ps.setInt(4, s.score);
ps.addBatch(); // 添加到batch
}
// 執行batch:
int[] ns = ps.executeBatch();
for (int n : ns) {
System.out.println(n + " inserted."); // batch中每個SQL執行的結果數量
}
}
```
執行batch和執行一個SQL不同點在于,需要對同一個`PreparedStatement`反復設置參數并調用`addBatch()`,這樣就相當于給一個SQL加上了多組參數,相當于變成了“多行”SQL。
第二個不同點是調用的不是`executeUpdate()`,而是`executeBatch()`,因為我們設置了多組參數,相應地,返回結果也是多個`int`值,因此返回類型是`int[]`,循環`int[]`數組即可獲取每組參數執行后影響的結果數量。
- Java自動化測試
- 第一章:Java:基礎內容
- 1.1:Java:Hello Word
- 1.2:Java:熱身
- 1.3:Java:注釋
- 1.4:Java:標識符
- 1.5:Java:常量
- 1.6:Java:基本數據類型
- 1.7:Java:引用類型
- 1.8:Java:String類
- 第二章:Java:運算符
- 2.1:Java:算數運算符
- 2.2:Java:關系運算符
- 2.3:Java:邏輯運算
- 2.4:Java:賦值運算符
- 2.5;Java:三元運算符
- 2.6:Java:位運算符
- 第三章:Java:循環控制語句
- 3.1:Java:for循環
- 3.2:Java:while循環
- 3.3:Java:switch
- 3.4:Java:if else
- 3.5:Java:練習題
- 第四章:Java:函數與全局/局部變量
- 4.1:Java:局部變量
- 4.2:Java:全局變量
- 第五章:Java:方法
- 5.1:Java:初識方法
- 5.2:Java:方法調用
- 5.3:Java:方法重載
- 5.4:Java:構造方法
- 5.5:Java:方法的注意事項
- 第六章:Java:面向對象
- 6.1:Java:小案例
- 6.2:Java:this 關鍵字
- 6.3:Java:super 關鍵字
- 6.4:Java:static 關鍵字
- 6.5:Java:final關鍵字
- 6.6:Java:instanceof 運算符
- 6.7:Java:面向對象之封裝
- 6.8:Java:面向對象之繼承
- 6.9:Java:面向對象之多態
- 第七章:Java:面向對象高級進階
- 7.1:Java:抽象類
- 7.2:Java:Java中String類
- 7.3:Java:interface接口
- 7.4:Java:ArrayList
- 7.5:Java:HashSet
- 7.6:Java:HashMap
- 7.7:Java:反射(reflection)
- 第八章:Java:日志以及異常捕獲
- 8.1:Java:log4j
- 8.2:Java:異常初識基礎
- 8.3:Java:未被捕獲的異常
- 8.4:Java:try和catch的使用
- 8.5:Java:多重catch語句的使用
- 8.6:Java:throws/throw 關鍵字
- 8.7:Java:finally關鍵字
- 8.8:Java:自定義異常
- 第九章:Java:xml and IO
- 9.1:Java:IO基本概念
- 9.2:java:properties
- 9.3:Java:xml基本介紹
- 9.4:Java:xml操作實例
- 第十章:Java:JDBC編程
- 10.1:Java:JDBC介紹
- 10.2:Java:JDBC查詢
- 10.3:Java:JDBC插入
- 10.4:Java:Batch
- 10.5:Java:JDBC連接池
- 第十一章:Java:TestNG
- 11.1:java:TestNG簡介
- 11.2:Java:TestNG小實例
- 11.3:Java:TestNG.xml文件配置
- 11.4:Java:TestNG基本注解
- 11.5:Java:TestNG注解代碼
- 11.6:Java:TestNG預期異常
- 11.7:Java:TestNG忽略測試
- 11.8:Java:TestNG超時測試
- 11.9:Java:TestNG分組測試