`

Java用JDBC批处理插入

 
阅读更多

让我们看看如何使用JDBC API在Java中执行批量插入。虽然你可能已经知道,但我会尽力解释基础到复杂的场景。

 
在此笔记里,我们将看到我们如何可以使用像Statement和PreparedStatement JDBC API来批量在任何数据库中插入数据。此外,我们将努力探索一些场景,如在内存不足时正常运行,以及如何优化批量操作。
 
首先,使用Java JDBC基本的API批量插入数据到数据库中。
 

Simple Batch - 简单批处理

 我把它叫做简单批处理。要求很简单,执行批量插入列表,而不是为每个INSERT语句每次提交数据库,我们将使用JDBC批处理操作和优化性能。

 
想想一下下面的代码:

Bad Code

String [] queries = {

    "insert into employee (name, city, phone) values ('A', 'X', '123')",

    "insert into employee (name, city, phone) values ('B', 'Y', '234')",

    "insert into employee (name, city, phone) values ('C', 'Z', '345')",

};

Connection connection = new getConnection();

Statement statemenet = connection.createStatement();

for (String query : queries) {

    statemenet.execute(query);

}

statemenet.close();

connection.close();

 

 这是糟糕的代码。它单独执行每个查询,每个INSERT语句的都提交一次数据库。考虑一下,如果你要插入1000条记录呢?这是不是一个好主意。

 

下面是执行批量插入的基本代码。来看看:

 

Good Code

 Connection connection = new getConnection();

Statement statemenet = connection.createStatement();

 

for (String query : queries) {

    statemenet.addBatch(query);

}

statemenet.executeBatch();

statemenet.close();

connection.close();

 

请注意我们如何使用addBatch()方法,而不是直接执行查询。然后,加入所有的查询,我们使用statement.executeBatch()方法一次执行他们。没有什么花哨,只是一个简单的批量插入。

 

请注意,我们已经从一个String数组构建了查询。现在,你可能会想,使其动态化。例如:

  

import java.sql.Connection;

import java.sql.Statement;

//...

 

Connection connection = new getConnection();

Statement statemenet = connection.createStatement();

for (Employee employee: employees) {

    String query = "insert into employee (name, city) values('"

            + employee.getName() + "','" + employee.getCity + "')";

    statemenet.addBatch(query);

}

statemenet.executeBatch();

statemenet.close();

connection.close();

  

 请注意我们是如何从Employee对象中的数据动态创建查询并在批处理中添加,插入一气呵成。完美!是不是?

 等等......你必须思考什么关于SQL注入?这样动态创建的查询SQL注入是很容易的。并且每个插入查询每次都被编译。

 为什么不使用PreparedStatement而不是简单的声明。是的,这是个解决方案。下面是SQL注入安全批处理。

 

SQL Injection Safe Batch - SQL注入安全批处理

 

思考一下下面代码:

 

import java.sql.Connection;

 

import java.sql.PreparedStatement;

 


//...

 


String sql = "insert into employee (name, city, phone) values (?, ?, ?)";

 

Connection connection = new getConnection();

 

PreparedStatement ps = connection.prepareStatement(sql);

 

 

 

for (Employee employee: employees) {

 

 

 

    ps.setString(1, employee.getName());

    ps.setString(2, employee.getCity());

    ps.setString(3, employee.getPhone());

    ps.addBatch();

}

ps.executeBatch();

ps.close();

connection.close();

 

 

 

 

 看看上面的代码。漂亮。我们使用的java.sql.PreparedStatement和在批处理中添加INSERT查询。这是你必须实现批量插入逻辑的解决方案,而不是上述Statement那个


这一解决方案仍然存在一个问题。考虑这样一个场景,在您想要插入到数据库使用批处理半万条记录。嗯,可能产生的OutOfMemoryError:

 

java.lang.OutOfMemoryError: Java heap space

    com.mysql.jdbc.ServerPreparedStatement$BatchedBindValues.<init>(ServerPreparedStatement.java:72)

    com.mysql.jdbc.ServerPreparedStatement.addBatch(ServerPreparedStatement.java:330)

    org.apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.java:171)

 

这是因为你试图在一个批次添加所有语句,并一次插入。最好的办法是将执行分批次。看看下面的解决方案

  

Smart Insert: Batch within Batch - 智能插入:将整批分批

 

这是一个简单的解决方案。考虑批量大小为1000,每1000个查询语句为一批插入提交。

 

String sql = "insert into employee (name, city, phone) values (?, ?, ?)";

 

Connection connection = new getConnection();

 

PreparedStatement ps = connection.prepareStatement(sql);

 

 

 

final int batchSize = 1000;

 

int count = 0;

 

 

 

for (Employee employee: employees) {

 

 

 

    ps.setString(1, employee.getName());

 

    ps.setString(2, employee.getCity());

 

    ps.setString(3, employee.getPhone());

    ps.addBatch();

 

    if(++count % batchSize == 0) {

        ps.executeBatch();

    }

}

ps.executeBatch(); // insert remaining records

ps.close();

connection.close();

 

 

 

这才是理想的解决方案,它避免了SQL注入和内存不足的问题。看看我们如何递增计数器计数,一旦BATCHSIZE 达到 1000,我们调用executeBatch()提交。

希望对你有帮助。

分享到:
评论

相关推荐

    Java_JDBC由浅入深

    7.1 实际项目中如何使用JDBC 41 7.2 DAO设计模式简介 42 7.3 DAO设计模式的实现 42 7.4 DAO设计模式与工厂模式的整合 49 7.5 DAO设计模式测试 52 第八节 JDBC对事务的支持 52 8.1 模拟转账 53 8.2 jdbc默认事务 54 ...

    jdbc连接数据库的方式2

    我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的...

    jfleet:JFleet使用来自JDBC的替代持久性方法来持久存储Java POJO的大型集合

    每个数据库都提供了某种技术来绕过标准JDBC命令插入大量信息,但是可以从Java访问: MySQL :使用语句。 PostgreSQL :使用命令。 在这两种情况下以及在不受支持的数据库中,都可以基于标准语句使用默认实现。 ...

    clickhouse4j:官方ClickHouse JDBC驱动程序的更简便快捷的替代方法

    应用了一堆微优化(例如,批处理插入现在快40% ) 添加; 支持JSON,JSONCompact选择; 针对Java 8和许多编译 用法 &lt; groupId&gt;cc.blynk.clickhouse &lt; artifactId&gt;clickhouse4j &lt; version&gt;1.4.4 ...

    jdbc基础和参考

    JDBC批处理: addBatch executeBatch Statement PreparedStatement Statement{ 1.获取连接 getConnection(); 2.创建Statement conn.createStatement(); 3.执行sql语句 String sql .... insert delete update ...

    fluent-jdbc:Java库,用于高效的本机SQL查询(通过JDBC)

    与Java 8 /功能代码很好地融合在一起,支持许多jdbc包装程序阻止/抽象的功能,并且重量轻(〜80K,无依赖项)。 FluentJdbc的主要功能: 功能性,流利的API 以单行的形式执行select / insert / update / delete ...

    Java Web编程宝典-十年典藏版.pdf.part2(共2个)

    Java Web编程宝典-十年典藏版.pdf 是PDF电子书,不是源码。共分2个包。 《Java Web编程宝典(十年典藏版)》是一本集技能、范例、项目和应用为一体的学习手册,书中介绍了应用Java Web进行程序开发的各种技术、技巧。...

    JAVA 范例大全 光盘 资源

    实例13 一维数组复制、插入和合并 32 实例14 数组排序 35 实例15 数组搜索 37 实例16 去掉数组重复数字 39 实例17 求质数(素数) 41 实例18 矩阵的加减和转置 43 实例19 数组实现顺序栈与队列 46 实例20 ...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例053 使用直接插入法 65 实例054 使用sort方法对数组进行排序 67 实例055 反转数组中元素的顺序 68 3.4 常用集合的使用 69 实例056 用动态数组保存学生姓名 69 实例057 用List集合传递学生信息 70 实例058 用...

    java范例开发大全源代码

     实例138 用iText生成Word文件 205  实例139 利用POI读取Word文件中的内容 208  7.3 字符流 209  实例140 按顺序创建文件 210  实例141 按顺序读取文件 211  实例142 追加文件内容 211  实例143 ...

    Java范例开发大全 (源程序)

     实例138 用iText生成Word文件 205  实例139 利用POI读取Word文件中的内容 208  7.3 字符流 209  实例140 按顺序创建文件 210  实例141 按顺序读取文件 211  实例142 追加文件内容 211  实例143 只显示...

    java范例开发大全

    实例138 用iText生成Word文件 205 实例139 利用POI读取Word文件中的内容 208 7.3 字符流 209 实例140 按顺序创建文件 210 实例141 按顺序读取文件 211 实例142 追加文件内容 211 实例143 只显示文件中指定的字符 214...

    Java范例开发大全(全书源程序)

    Java范例开发大全(全书源程序),目录如下: 第1篇 Java编程基础 第1章 Java开发环境的搭建(教学视频:9分钟) 2 1.1 理解Java 2 1.2 搭建Java所需环境 3 1.2.1 下载JDK 3 1.2.2 安装JDK 4 1.2.3 配置环境...

    java范例开发大全(pdf&源码)

    实例138 用iText生成Word文件 205 实例139 利用POI读取Word文件中的内容 208 7.3 字符流 209 实例140 按顺序创建文件 210 实例141 按顺序读取文件 211 实例142 追加文件内容 211 实例143 只显示文件中指定的字符 214...

    hbase phoenix sql

    嵌入式的JDBC驱动,实现了大部分的java.sql接口,包括元数据API 可以通过多部行键或是键/值单元对列进行建模 完善的查询支持,可以使用多个谓词以及优化的扫描键 DDL支持:通过CREATE TABLE、DROP TABLE及ALTER ...

    Java学习笔记-个人整理的

    {1.11.2.3}插入排序}{40}{subsubsection.1.11.2.3} {1.11.3}递归调用}{41}{subsection.1.11.3} {1.12}Java API}{41}{section.1.12} {1.13}Linux命令}{41}{section.1.13} {1.13.1}基本查看、移动}{41}{...

Global site tag (gtag.js) - Google Analytics