本篇講述如何使用JDBC對數據庫實現批處理操作。很多時候單條SQL命令不能滿足我們的需求,我們需要對數據庫一次實現很多操作,需要發送一批SQL命令給數據庫執行。
而JDBC也提供了相應的方法給我們實現批處理操作。分別使用Statement對象或者PreparedStatement對象。這兩種方式分別有着不同的運用場景:
⑴ 使用Statement對象
優點:能發送多條不同操作類型的SQL命令,也就是說在這發送的一批SQL語句中可以有各種增刪改查命令。
缺點:雖然能發送多條不同操作類型的SQL命令,但沒有預編譯,因此在數據庫這一批中的每條SQL都需要編譯和執行兩個步驟。
⑵ 使用PreparedStatement對象
優點:發送的是預編譯后的SQL語句,數據庫對這一批SQL命令只需要執行這一個步驟即可。
缺點:只能發送多條相同操作類型,但占位符參數可以不同的SQL命令。也就是說這一批SQL要么是更新,要么是添加等等。稍后會介紹。
操作:
① 無論是Statement對象還是PreparedStatement對象,內部都含有一個List集合來保存一批多條SQL語句。兩個對象都使用addBatch方法來添加每一條SQL語句(Statement使用有參的addBatch方法,PreparedStatement使用無參的addBatch方法,后面會介紹到)。
② 當Statement對象或PreparedStatement對象都添加完一批SQL之后,都使用executeBatch()方法來使數據庫執行批處理,完成后返回一個整型數組int[],該整型數組中的元素的順序對應於提交給Statement對象或PreparedStatement對象的SQL語句順序,如果返回的是大於或等於0的數則表示成功處理並給出執行所影響的行數。當然改數組還會是別的內容,具體請看相關API文檔:
③ 在每次執行完executeBatch()方法后,請一定要再調用clearBatch()方法,將清空Statement對象或PreparedStatement對象中List集合保存的SQL命令列表。
④ 在使用批處理操作時,且不可一次執行過多SQL命令,例如幾千萬次,尤其是在使用PreparedStatement對象的方式情況下,極容易造成程序內存溢出。對於要執行過多次的操作,請將執行次數再分成各小批分別執行。
下面分別以使用Statement對象和使用PreparedStatement對象的兩個例子來說明兩種批處理方式的不同之處。
例1:使用Statement對象進行批處理
在這個案例中,我使用Statement對象進行批處理操作同時包含了插入和修改兩種操作,如果該批處理成功執行就說明了使用Statement對象能進行不同類型的數據庫操作。
創建數據庫和表:
create database jdbcdemo; use jdbcdemo; create table batchtest ( id int primary key, name varchar(40) )
創建工程,在工程中導入數據庫連接驅動的jar包。在【src】目錄下新建一個database.properties文件,內容如下:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcdemo
username=root
password=root
構建JDBC的工具類,包括注冊驅動,獲取連接,釋放資源和連接等,這部分同《JDBC操作數據庫的學習(2)》中相同,此處略。
使用Statement對象進行批處理操作:

1 public void statementbatch() throws SQLException { 2 Connection conn = null; 3 Statement st = null; 4 ResultSet rs = null; 5
6 try{ 7 conn = JdbcUtils.getConnection(); 8 st = conn.createStatement(); 9 String sql1 = "insert into batchtest(id,name) values(1,'Ding')"; 10 String sql2 = "update batchtest set name='LRR' where id=1 "; 11
12 st.addBatch(sql1); 13 st.addBatch(sql2); 14
15 st.executeBatch(); 16 st.clearBatch(); 17 }finally{ 18 JdbcUtils.release(conn, st, rs); 19 } 20 }
查看數據庫執行情況:
第一條SQL是插入命令,插入一個id列為1,name列為“Ding”的行數據項;第二條SQL是修改命令,將id列為1的行數據項的name列修改為“LRR”。
例2:使用PreparedStatement對象進行批處理
因為PreparedStatement對象只能執行相同的操作類型,因此在該案例中我向數據庫中執行插入的批處理SQL。
創建數據庫和表(與例1相同):
create database jdbcdemo; use jdbcdemo; create table batchtest ( id int primary key, name varchar(40) )
創建工程,在工程中導入數據庫連接驅動的jar包。在【src】目錄下新建一個database.properties文件,內容如下:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcdemo
username=root
password=root
構建JDBC的工具類,包括注冊驅動,獲取連接,釋放資源和連接等,這部分同《JDBC操作數據庫的學習(2)》中相同,此處略。
使用PreparedStatement對象進行批處理操作:

1 public void preparedStatementBatch() throws SQLException { 2 Connection conn = null; 3 PreparedStatement st = null; 4 ResultSet rs = null; 5
6 try{ 7 conn = JdbcUtils.getConnection(); 8 String sql = "insert into batchtest(id,name) values(?,?)"; 9 st = conn.prepareStatement(sql); 10
11 st.setInt(1, 1); //設置id列
12 st.setString(2, "Ding"); //設置name列
13 st.addBatch(); 14
15 st.setInt(1, 2); //設置id列
16 st.setString(2, "LRR"); //設置name列
17 st.addBatch(); 18
19 st.executeBatch(); 20 st.clearBatch(); 21 }finally{ 22 JdbcUtils.release(conn, st, rs); 23 } 24 }
查看數據庫執行情況:
可以看到使用PreparedStatement對象只能對同一條SQL語句中的占位符替代不同參數的批處理操作。
正是基於這樣的設計,使我們可以利用循環,對一些具有循環性質的替代占位符的參數使用PreparedStatement對象進行批處理,還是上面的例2 ,先清空batchtest表,其他不變,就改變程序為:

1 public void preparedStatementBatch() throws SQLException { 2 Connection conn = null; 3 PreparedStatement st = null; 4 ResultSet rs = null; 5
6 try{ 7 conn = JdbcUtils.getConnection(); 8 String sql = "insert into batchtest(id,name) values(?,?)"; 9 st = conn.prepareStatement(sql); 10
11 for(int i=1;i<=5;i++) { 12 st.setInt(1, i); //設置id列
13 st.setString(2, "a"+i); //設置name列
14 st.addBatch(); 15 } 16
17 st.executeBatch(); 18 st.clearBatch(); 19 }finally{ 20 JdbcUtils.release(conn, st, rs); 21 } 22 }
查看數據庫執行情況:
對於每次循環,都將在調用addBatch方法后將占位符已經被替代為參數的SQL語句存入PreparedStatement對象中的集合里,在下一次循環就可以進行新的占位符替代並再次存入新的SQL語句,存入SQL語句的次數和循環次數相關,因此如果循環次數過大,那么按上面的例子也將會導致程序內存溢出,解決方法就是將循環次數再分成小的循環批次一批一批地執行。
解決:
基本到此就將使用JDBC操作數據庫進行批處理介紹完畢,通常我們會使用PreparedStatement對象的方式多一些,同時最后再說明一點,以上的案例我們都是使用的是MySQL數據庫,對於大數據量的批處理操作,MySQL數據庫的執行相比Oracle數據庫的速度來說還差的很多,因此如果要對數據庫執行大量的批處理操作,建議使用Oracle數據庫。