使用JDBC一次插入多条记录(以MySQL为例)

阅读本文需要的先修知识:

  • 最基本的SQL语句
  • 最基本的JDBC操作(如插入单条记录)

如急需使用请直接看最后一段代码。

在JDBC中,插入记录最简单的方法是使用executeUpdate()方法,但该方法中的参数只能是单条SQL语句,其实对于需要INSERT或者UPDATE多条记录的情况,JDBC也提供了批量更新的机制。

1.事务

批量更新基于事务处理,JDBC提供了两个方法void commit()void rollback(),这两个函数的用法正如大部分SQL数据库中提供的事务处理语句一样,commit()方法用来提交多条语句,rollback()方法用来回滚至执行本次事务之前的状态。

请看如下代码:

public static void main(String[] args) {
        Connection conn;
        Statement stmt;

        try {

            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            //DB_URL,USER,PASS均为事先定义好的字符串,分别代表数据库地址,登录用户名,密码
            stmt = conn.createStatement();

            conn.setAutoCommit(false);
            stmt.executeUpdate("INSERT INTO test(id, name, tel) VALUES(1, ‘Chandler‘, ‘1111111‘)");
            stmt.executeUpdate("INSERT INTO test(id, name, tel) VALUES(2, ‘Joey‘, ‘2222222‘)");
            stmt.executeUpdate("INSERT INTO test(id, name, tel) VALUES(3, ‘Rachel‘, ‘3333333‘)");
            conn.commit();

            stmt.executeUpdate("INSERT INTO test(id, name, tel) VALUES(4, ‘Monica‘, ‘4444444‘)");
            stmt.executeUpdate("INSERT INTO test(id, name, tel) VALUES(5, ‘Ross‘, ‘5555555‘)");
            stmt.executeUpdate("INSERT INTO test(id, name, tel) VALUES(6, ‘Phoebe‘, ‘666666‘)");

            stmt.close();
            conn.close();

        } catch (SQLException se) {
            se.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

在执行命令之前,我们首先调用了一个参数为falsesetAutoCommit()方法,这个方法的作用是使得在其之后执行的命令不会立即被提交给数据库,而是等到下一次调用commit()方法时,才一次性全部提交。

在上面的代码中,我们首先执行了3条插入语句,然后进行了一次提交,之后又执行了3条插入语句,不同的是这3条插入语句执行后没有进行提交。执行这个程序之后,结果是这样的。

mysql> select * from test;
+----+----------+---------+
| id | name     | tel     |
+----+----------+---------+
|  1 | Chandler | 1111111 |
|  2 | Joey     | 2222222 |
|  3 | Rachel   | 3333333 |
+----+----------+---------+
3 rows in set (0.00 sec)

可见后面3条插入命令因为还没有commit,所以是没有生效的。就这个结果来看,利用这样的方法,我们就可以先执行多条插入语句,再进行一次commit,达到一次插入多条记录的效果。但事实上,这样和不使用事务没有太大的区别,性能也没有什么提高,真正要实现批量插入,我们还需要借助JDBC的批量更新机制。

2.批量更新

在这里我们主要需要使用两个方法,分别是void addBatch(String command)int[] executeBatch()。我们通过对上面的代码做一些改动来探究这两个方法的用法。

public static void main(String[] args) {
        Connection conn;
        Statement stmt;

        try {

            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            //DB_URL,USER,PASS均为事先定义好的字符串,分别代表数据库地址,登录用户名,密码
            stmt = conn.createStatement();

            conn.setAutoCommit(false);
            stmt.addBatch("INSERT INTO test(id, name, tel) VALUES(1, ‘Chandler‘, ‘1111111‘)");
            stmt.addBatch("INSERT INTO test(id, name, tel) VALUES(2, ‘Joey‘, ‘2222222‘)");
            stmt.addBatch("INSERT INTO test(id, name, tel) VALUES(3, ‘Rachel‘, ‘3333333‘)");
            stmt.addBatch("INSERT INTO test(id, name, tel) VALUES(4, ‘Monica‘, ‘4444444‘)");
            stmt.addBatch("INSERT INTO test(id, name, tel) VALUES(5, ‘Ross‘, ‘5555555‘)");
            stmt.addBatch("INSERT INTO test(id, name, tel) VALUES(6, ‘Phoebe‘, ‘666666‘)");

            int[] counts = stmt.executeBatch(); //执行Batch中的全部语句
            conn.commit();                      //提交到数据库
            for (int i : counts) {
                if (i == 0) {
                    conn.rollback();
                }
            }

            conn.setAutoCommit(true);   //在完成批量操作后恢复默认的自动提交方式,提高程序的可扩展性

            stmt.close();
            conn.close();

        } catch (SQLException se) {
            se.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

addBatch()方法每调用一次,就相当于往一个假想的“批处理”中添加了一条语句,这些语句在下一次调用 executeBatch()方法时一次性全部执行,在此之后,我们再次调用一个commit()将所作的更改提交到数据库。

executeBatch()方法的返回值是一个int数组,里面保存了本次执行的每条语句的返回值,即受到影响的记录的行数,在本例中,数组中的所有值均应为1,如果为0则说明插入失败,我们可以选择进行回滚或者报错。

3.预备语句

每次调用addBatch()方法时都需要输入一长串SQL语句显得十分繁琐,在操作列数比较多的表时就更是如此,为了避免这样的情况,我们可以使用预备语句。

预备语句的用法有点类似于printf()的用法,当我们使用printf进行输出时,往往会在字符串中插入几个像%d%c这样的占位符,至于这些位置具体的值,我们则在字符串后面再专门指定。

预备语句的占位符没有按类型进行区分,只有一种——?,请看如下代码:

PreparedStatement pstm = conn.prepareStatement("INSERT INTO test(id, name, tel) VALUES(?, ?, ?")
pstm.setInt(1, 1);
pstm.setString(2, ‘Chandler‘);
pstm.setString(3, ‘1111111‘);
pstm.executeUpdate();

首先我们使用带占位符?的SQL语句初始化一个PreparedStatement对象,然后分别使用setInt()方法和setString()方法给对应的位置填值,除了这两种方法还有很多其他类型的赋值方法,具体可以查阅官方文档或者利用IDE的自动补全功能进行查看,这一类方法的参数都是类似的,第一个参数指明要给第几个?进行赋值,第二个参数要赋的;在给所有的位置赋值之后,我们调用executeUpdate()方法执行这条语句。

上面代码的功能和下面的等同:

Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO test(id, name, tel) VALUES(1, ‘Chandler‘, ‘1111111‘)");

表面看来下面使用普通语句的方法更简洁,但当我们要操作的记录数变多,乃至成千上万条时,预备语句的优势就会体现出来。最后,我们将一开始的程序使用预备语句+批量更改+事务重写一遍:

public static void main(String[] args) {
        Connection conn;
        PreparedStatement pstm;

        try {

            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            //DB_URL,USER,PASS均为事先定义好的字符串,分别代表数据库地址,登录用户名,密码

            conn.setAutoCommit(false);
            pstm = conn.prepareStatement("INSERT INTO test(id, name, tel) VALUES(?, ?, ?");

            pstm.setInt(1, 1);
            pstm.setString(2, "Chandler");
            pstm.setString(3, "1111111");
            pstm.addBatch();

            pstm.setInt(1, 2);
            pstm.setString(2, "Joey");
            pstm.setString(3, "2222222");
            pstm.addBatch();

            pstm.setInt(1, 3);
            pstm.setString(2, "Rachel");
            pstm.setString(3, "3333333");
            pstm.addBatch();

            pstm.setInt(1, 4);
            pstm.setString(2, "Monica");
            pstm.setString(3, "4444444");
            pstm.addBatch();

            pstm.setInt(1, 5);
            pstm.setString(2, "Ross");
            pstm.setString(3, "5555555");
            pstm.addBatch();

            pstm.setInt(1, 6);
            pstm.setString(2, "Phoebe");
            pstm.setString(3, "666666");
            pstm.addBatch();

            int[] counts = pstm.executeBatch(); //执行Batch中的全部语句
            conn.commit();                      //提交到数据库
            for (int i : counts) {
                if (i == 0) {
                    conn.rollback();
                }
            }

            conn.setAutoCommit(true);   //在完成批量操作后恢复默认的自动提交方式,提高程序的可扩展性

            pstm.close();
            conn.close();

        } catch (SQLException se) {
            se.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
参考文献
  1. Java核心技术·卷2:高级特性(原书第9版)(截止我写这篇文章时,已经出到第10版)
  2. MySQL必知必会
实验所用环境
  1. Windows 10(1809)
  2. jdk 1.8.0_101
  3. MySQL Sserver 8.0.13 for Win64 on x86_64

原创文章,转载请注明出处

原文地址:https://www.cnblogs.com/HanochShi/p/10112604.html

时间: 2024-10-09 16:11:10

使用JDBC一次插入多条记录(以MySQL为例)的相关文章

通过 JDBC 向指定的数据表中插入一条记录,查询记录

//通过 JDBC 向指定的数据表中插入一条记录 /*  * 1.Statement: 用于执行SQl语句的对象  *  通过Connection 的createStatement()方法来获取  *  通过executeUptate(sql) 可执行sql语句  *  传入的sql 可以是 insert , update, delete 但不能是select  * 2.Connection 和 Statement 需要关闭  *  需要在finally中关闭  * 3.关闭的顺序:先关闭后获取

插入一条记录并获取自增的id

Connection connection = (Connection) dbcp.getConn(); int affectRows = qr.update(connection, sql,params); BigInteger id = BigInteger.ZERO ; id = qr.query(connection, "SELECT LAST_INSERT_ID()", new ScalarHandler(1)); //获取新增记录的自增主键 这个是通过dbutils来获取的

SQL 一次插入多条记录

本文介绍如何快速插入多条数据到数据表中,以满足sql语句学习或项目测试的需要. 本文非原创,是对移步原文的重新整理. 如有以下表格,如图: 1,原始添加记录的方式,sql语句如下: 1 insert into City(Code,CityCName) values('TS','唐山'); 2,使用Union执行插如操作,sql语句如下: 1 insert into City(Code,CityCName) 2 select 'ZZ','郑州' 3 union 4 select 'HD','邯郸'

无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)

1.listview入门,自定义的数据适配器 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent&

18.一次性插入多条记录

use MySchool --一次性插入多条记录-- insert into grade values(4,'工具') insert into Grade (GradeName) select 'aaa' union all --只有全部写了union all才不会去除重复记录 select 'aaa' union all select 'aaa' union all select 'aaa' union all select 'bb' union all select 'bb' --union

C# access数据库软件使用事务插入多条记录

C# access数据库软件使用事务插入多条记录 protected void Button1_Click(object sender, EventArgs e) { /*=============测试通过===============*/ OleDbConnection con = new OleDbConnection(“Provider=Microsoft.Jet.OleDb.4.0;Da ta Source=C:/Inetpub/wwwroot/DotNetArticle/App_Dat

AX 插入一条记录提示表记录已经存在,但是该记录实际上是不存在的。

做测试的时候遇到一个情况"AX 插入一条记录提示表记录已经存在,但是该记录实际上是不存在的." 检查到该表(TABLE_ABC)所有的key都是AllowDuplicate的, 继续检查表属性发现 createdRecIdxIdx设置为Yes, 启用了RecId作为唯一键. 因此推测 应该是该表的recid 的nextvalue 数据不对了. 想办法刷新 recid . 在sql 后台 1. 计算 Table_ABC目前最大的RecId declare @maxRecId int64

一次插入多条记录 [mysql]

调用多次INSERT语句不就可以插入多条记录了吗?但使用这种方法要增加服务器的负荷,因为,执行每一次SQL服务器都要同样对SQL进行分析.优化等操作.幸好MySQL提供了另一种解决方案,就是使用一条INSERT语句来插入多条记录.这并不是标准的SQL语法,因此只能在MySQL中使用. INSERT INTO users(name, age)  VALUES('姚明', 25), ('比尔.盖茨', 50), ('火星人', 600); 上面的INSERT 语句向users表中连续插入了3条记录.

一条insert语句批量插入多条记录 AND 多条件游标更新 变CASE WHEN更新法提高速度

一条insert语句批量插入多条记录 常见的insert语句,向数据库中,一条语句只能插入一条数据: insert into persons (id_p, lastname , firstName, city ) values(204,'haha' , 'deng' , 'shenzhen'); (如上,仅插入了一条记录) 怎样一次insert插入多条记录呢? 使用示例: insert into persons (id_p, lastname , firstName, city ) values