在此笔记里,我们将看到我们如何可以使用像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.(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()提交。

来源: http://itindex.blog.51cto.com/3619105/801447

java jdbc 批处理_Java JDBC批处理插入数据操作相关推荐

  1. Java JDBC批处理插入数据操作

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

  2. 【JDBC】PreparedStatement实现批量插入数据

    题目:[JDBC]PreparedStatement实现批量插入数据 前言: PreparedStatement除了解决Statement的拼串.sql注入问题之外,还可以实现以下操作 Prepare ...

  3. jdbc 3种获得mysql插入数据的自增字段值的方法_JDBC 3种获得mysql插入数据的自增字段值的方法...

    JDBC 3种获得mysql插入数据的自增字段值的方法. 1. Retrieving AUTO_INCREMENT Column Values using Statement.getGenerated ...

  4. unordered_multimap学习之插入数据操作insert,emplace ,emplace_hint

    本篇学习unordered_multimap的插入数据操作,具体的函数如下: insert (C++11) 插入元素或结点 (C++17 起) (公开成员函数) emplace (C++11) 原位构 ...

  5. jdbc 3种获得mysql插入数据的自增字段值的方法_【JDBC】向数据表插入数据时,自动获取生成的主键...

    数据表设计时,一般都会有一个主键(Key)(自己指定),有时也可以使用联合主键: 有许多数据库提供了隐藏列为表中的每行记录分配一个唯一键值(如:rowid): 当我们没有指定哪一列作为主键key时,数 ...

  6. java mysql 插入 乱码_java向mysql插入数据乱码问题的解决方法

    遇到java向mysql插入数据乱码问题,如何解决? MySQL默认编码是latin1 mysql> show variables like 'character%'; +----------- ...

  7. java jdbc事务_Java JDBC事务管理和保存点

    java jdbc事务 Transaction Management in java is required when we are dealing with relational databases ...

  8. JDBC进行批量插入数据操作

    目录 1.方式一:使用PreparedStatement 2.方式二:使用addBatch(),excuteBatch(),clearBatch() 3.方式三:设置不允许自动提交数据 4.总结 1. ...

  9. java使用poi给excel文件插入数据

    excel模板文件 代码 package com.example.demo;import java.io.File; import java.io.FileInputStream; import ja ...

最新文章

  1. 第五课:系统目录及ls·文件类型及alias命令介绍
  2. 数据探查与可视化平台
  3. android.support不统一的问题
  4. java 无符号运算_java位运算和无符号运算
  5. HTTP Error 500.19 – Internal Server Error – 0x80070021 (IIS 8.5)
  6. Dubbo to Mesh 云原生架构改造方案解析
  7. 刚被通用收编的这家创业公司,号称能把LiDAR成本降低近100%
  8. 视频讲解(RCNN,FasterRCNN,FPN,MaskRCNN)
  9. 周学习进度---05
  10. 图解JVM内存三大核心区域及其JVM内存案例实战剖析
  11. 中兴威武3android驱动,中兴威武3
  12. HP M1136无法打印的解决方法
  13. React-pdf:pdf预览插件实践
  14. Java:判断某年是闰年or平年并输出某月的天数
  15. pandas 二维表与一维记录的转换
  16. 全国最大孔雀养殖基地在哪里???
  17. ElasticSearch——路由(_routing)机制
  18. 大数据和java就业前景_Java大数据就业方向
  19. BPI-M1P(全志A20)刷Android启动卡之后启动的过程
  20. 教你长高 男的没有1米8的 女的没1.65都要看啊

热门文章

  1. 【温故而知新】HTTP 报文
  2. 判断两个数组有相同的数据
  3. springboot 远程调用shell脚本,环境为windows
  4. markdown编辑器基础语法总结
  5. 浅谈 TypeScript【上】-- Flow 静态类型检查工具
  6. 【树莓派】最常用的树莓派 Linux 命令及说明
  7. C#LeetCode刷题之#874-模拟行走机器人​​​​​​​(Walking Robot Simulation)
  8. Linux入门学习(八)
  9. 怎么解决python遇到问题_新手常见Python错误及异常解决处理方案
  10. php控制台脚本错误输出到php_errors.log