測試採用MySQL數據庫,建立以下表;java
CREATE TABLE `batch_test` ( `id` int(11) NOT NULL , PRIMARY KEY (`id`) )
測試代碼:mysql
Connection conn = null; Statement stmt = null; try { conn = DBUtils.getConnection(); conn.setAutoCommit(false); stmt = conn.createStatement(); stmt.addBatch("INSERT INTO batch_test(id) VALUES (1)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (2)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (3)"); stmt.executeBatch(); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.close(conn, stmt); }
結果:sql
mysql> select * from batch_test; Empty set
修改代碼,增長commit()數據庫
Connection conn = null; Statement stmt = null; try { conn = DBUtils.getConnection(); conn.setAutoCommit(false); stmt = conn.createStatement(); stmt.addBatch("INSERT INTO batch_test(id) VALUES (1)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (2)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (3)"); stmt.executeBatch(); // ************ conn.commit(); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.close(conn, stmt); }
結果:app
mysql> select * from batch_test; +----+ | id | +----+ | 1 | | 2 | | 3 | +----+ 3 rows in set
對比上面兩個測試,說明在執行executeBatch()後必須再執行commit(), executeBatch不會執行commit操做;測試
接着3.1的測試數據,目前表batch_test中已經有三條記錄,id字段是主鍵,而且已經存在三個值(1,2,3),我再依次添加4條insert命令,id值順序爲(4,5,1,6),當執行executeBatch時第三條記錄(id=1)應該會失敗,且拋出異常。spa
代碼以下:code
try { conn = DBUtils.getConnection(); conn.setAutoCommit(false); stmt = conn.createStatement(); stmt.addBatch("INSERT INTO batch_test(id) VALUES (4)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (5)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (1)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (6)"); stmt.executeBatch(); System.out.println("executeBatch"); conn.commit(); System.out.println("commit"); } catch (BatchUpdateException e) { e.printStackTrace(); System.out.println("UpdateCounts -> " + Arrays.toString(e.getUpdateCounts())); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.close(conn, stmt); }
執行executeBatch()時拋異常BatchUpdateException,輸出:get
java.sql.BatchUpdateException: Duplicate entry '1' for key 'PRIMARY'
at com.mysql.jdbc.StatementImpl.executeBatch(StatementImpl.java:1110)
at com.tiza.test.db.BatchExecTest.main(BatchExecTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
UpdateCounts -> [1, 1, -3, 1]it
結果:
mysql> select * from batch_test; +----+ | id | +----+ | 1 | | 2 | | 3 | +----+ 3 rows in set
根據結果可知,批量操做當出現一條SQL命令失敗,會拋異常,而且UpdateCounts顯示,除了id=1的記錄執行失敗,其餘三條都成功了。 可是這裏拋異常後就沒有執行commit,那若是執行commit是否是三條成功的(id=4,id=5,id=6)就會提交到數據庫?
進一步測試,在拋BatchUpdateException後依然作commit,代碼以下:
Connection conn = null; Statement stmt = null; try { conn = DBUtils.getConnection(); conn.setAutoCommit(false); stmt = conn.createStatement(); stmt.addBatch("INSERT INTO batch_test(id) VALUES (4)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (5)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (1)"); stmt.addBatch("INSERT INTO batch_test(id) VALUES (6)"); stmt.executeBatch(); System.out.println("executeBatch"); conn.commit(); System.out.println("commit"); } catch (BatchUpdateException e) { e.printStackTrace(); System.out.println("UpdateCounts -> " + Arrays.toString(e.getUpdateCounts())); // ********************** try { conn.commit(); } catch (SQLException e1) { e1.printStackTrace(); } // ********************** } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.close(conn, stmt); }
輸出:
java.sql.BatchUpdateException: Duplicate entry '1' for key 'PRIMARY'
at com.mysql.jdbc.StatementImpl.executeBatch(StatementImpl.java:1110)
at com.tiza.test.db.BatchExecTest.main(BatchExecTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
UpdateCounts -> [1, 1, -3, 1]
結果:
mysql> select * from batch_test; +----+ | id | +----+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +----+ 6 rows in set
至此問題二答案已經出來了,批量提交過程當中雖然在執行executeBatch時當部分命令出現異常,可是隻要繼續執行commit,其中成功執行的命令仍是會commit到數據庫的。
問題一:Statement的executeBatch方法是否會執行commit操做,是否還須要再執行一次commit()?
答: executeBatch不會執行commit,在執行完executeBatch後必須再執行commit;
問題二:執行批量操做的過程當中,若是其中有部分命令執行失敗,其餘執行成功的命令是否會提交到數據庫?
答: 批量操做執行executeBatch時部分命令執行失敗會拋BatchUpdateException異常,可是隻要繼續執行commit,其餘成功執行的命令依然會提交到數據庫,不然不關執行成功與否都不會提交到數據庫。