`

强大的批处理功能

    博客分类:
  • jdbc
阅读更多
在此笔记里,我们将看到我们如何可以使用像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()提交。
分享到:
评论

相关推荐

    非常好用的批处理功能强大

    非常好用,就收一分吧,希望大家支持,能够让它更加完善

    万能批处理工具,功能强大

    万能批处理工具,功能强悍,保证好用,简单使用

    功能强大的批处理文件

    功能强大的批处理文件,找了很久才找到的,与大家共享。

    非常批处理(功能强大)

    非常简单的批处理执行文件,然后可以看到代码的。灵活,为工作和学习研究减轻了负担

    万能批处理工具包 bat 下载 源代码 功能强大

    万能批处理工具包 bat 下载 源代码 功能强大

    usb屏蔽批处理,功能强大

    用来屏蔽usb驱动文件的批处理,禁用解开方便

    万能批处理,功能强大呀

    这个功能可大了,集合了各个程序,定时关机,这个不错吧

    批处理程序编程软件

    BatProject是一款批处理编辑软件,致力于为用户打造功能最强大、最简洁的批处理开发环境 1、高亮代码  可以实时高亮正在编辑的代码,无任何延迟 2、自动补全  输入时实时弹出下拉框显示相关信息(如输入...

    DOS批处理实例教程

    批处理有一个很鲜明的特点:使用方便、灵活,功能强大,自动化程度高。我不想让自己写的教程枯燥无味,因为牵缠到代码(批处理的内容算是代码吧?)的问题本来就是枯燥的,很少有人能面对满屏幕的代码而静下心来。...

    好用的万能批处理工具

    批处理,也称为批处理脚本,英文译为BATCH,批处理文件后缀BAT就取的前三个字母。它的构成没有固定格式,只要遵守以下这条就ok了:每一行可视为...批处理有一个很鲜明的特点:使用方便、灵活,功能强大,自动化程度高。

    无敌文件批处理大师 V1.2

    您见过如此功能强大的文件批处理软件吗?无敌文件批处理大师就是这么一款功能超强的软件产品,计算机用户必备!口号:处理一切“文件批量处理”。功能:文件和文件夹各种方式的更名、批量文件分割、文件内容替换、...

    无敌文件批处理大师

    您见过如此功能强大的文件批处理软件吗?无敌文件批处理大师就是这么一款功能超强的软件产品,计算机用户必备!口号:处理一切“文件批量处理”。功能:文件和文件夹各种方式的更名、批量文件分割、文件内容替换、...

    spm 批处理工具,简单实用,方便神经影像学者使用

    spm功能强大,但是从spm99-spm8都不具有批处理功能。本插件解决了该问题

    万能批处理工具箱

    万能批处理工具箱,功能强大,希望大家支持,能够让它更加完善!

    经典批处理程序(必备哦)

    批处理的功能很强大,可以自动完成很多任务,有很多病毒也有批处理的基础,大家最好都学学,这是绝对经典的批处理程序!如果大家想学好批处理,一定要下啊!

    批处理程序开发VisualBatV2.5绿色版

    ·添加了强大的文档命令查询帮助功能,含盖从dos到xp的所有cmd命令; 支持批处理转换EXE应用程序功能 集成系统DOS命令 快速开发批处理程序 声明:本程序做过加壳保护,极少部分杀毒软件会存在误报,纯属正常。 ...

    批处理命令大全.rar

    批处理有一个很鲜明的特点:使用方便、灵活,功能强大,自动化程度高。我不想让自己写的教程枯燥无味,因为牵缠到代码(批处理的内容算是代码吧?)的问题本来就是枯燥的,很少有人能面对满屏幕的代码而静下心来。...

    DOS批处理实例教程,值得下载

    批处理有一个很鲜明的特点:使用方便、灵活,功能强大,自动化程度高。我不想让自己写的教程枯燥无味,因为牵缠到代码(批处理的内容算是代码吧?)的问题本来就是枯燥的,很少有人能面对满屏幕的代码而静下心来。...

    多功能超强批处理(杀毒 优化 系统操作)

    此批处理集中了网上众多批处理的优点,功能强大! 而且代码基本涵盖了系统的方方面面,如果学习批处理的话,完全可以借鉴此代码。。。。

Global site tag (gtag.js) - Google Analytics