博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JDBC批量提交SQL的几点问题解答
阅读量:7173 次
发布时间:2019-06-29

本文共 5129 字,大约阅读时间需要 17 分钟。

hot3.png

1. 疑问

  • 问题一:Statement的executeBatch方法是否会执行commit操作,是否还需要再执行一次commit()?
  • 问题二:执行批量操作的过程中,如果其中有部分命令执行失败,其他执行成功的命令是否会提交到数据库?

2. 环境

    测试采用MySQL数据库,创建如下表;

CREATE TABLE `batch_test` (`id`  int(11) NOT NULL ,PRIMARY KEY (`id`))

3. 测试

3.1. 问题一测试

    测试代码:

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);}

    结果:

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);}

    结果:

mysql> select * from batch_test;+----+| id |+----+|  1 ||  2 ||  3 |+----+3 rows in set

对比上面两个测试,说明在执行executeBatch()后必须再执行commit(), executeBatch不会执行commit操作;

3.2. 问题二测试

    接着3.1的测试数据,目前表batch_test中已经有三条记录,id字段是主键,并且已经存在三个值(1,2,3),我再依次添加4条insert命令,id值顺序为(4,5,1,6),当执行executeBatch时第三条记录(id=1)应该会失败,且抛出异常。

    代码如下:

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,输出:

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 |+----+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到数据库的。

4. 总结

问题一:Statement的executeBatch方法是否会执行commit操作,是否还需要再执行一次commit()?

答: executeBatch不会执行commit,在执行完executeBatch后必须再执行commit;

 

问题二:执行批量操作的过程中,如果其中有部分命令执行失败,其他执行成功的命令是否会提交到数据库?

答: 批量操作执行executeBatch时部分命令执行失败会抛BatchUpdateException异常,但是只要继续执行commit,其他成功执行的命令依然会提交到数据库,否则不关执行成功与否都不会提交到数据库。

转载于:https://my.oschina.net/shipley/blog/703313

你可能感兴趣的文章
对中间过程进行调试
查看>>
怎样获取数据库中某一个字段长度最长的那条记录
查看>>
yourphp常用标签
查看>>
anchor_target_layer层解读
查看>>
7.6 服务远程暴露 - 注册服务到zookeeper
查看>>
Lua------------------unity与lua的热更新
查看>>
【Win 10 应用开发】UI Composition 札记(一):视图框架的实现
查看>>
JavaScript面向对象总结
查看>>
分布式系统理论基础,以及选举,多数派,租约
查看>>
Breadth-first search 算法(Swift版)
查看>>
Vue.js系列之四计算属性和观察者
查看>>
pycharm 对代码做静态检查
查看>>
Python的sys.argv使用说明 通过终端写入环境变量
查看>>
在Windows上安装Nexus
查看>>
用mysql查询某字段是否有索引
查看>>
ubuntu 查看进程,查看服务
查看>>
Cisco DHCP Snooping + IPSG 功能实现
查看>>
Linux命令_用户身份切换
查看>>
学习在.NET Core中使用RabbitMQ之启动和基础(一)
查看>>
支付业务的数据库表的设计
查看>>