JDBC的PreparedStatement启动事务使用批处理executeBatch()
JDBC使用MySQL处理大数据的时候,自然而然的想到要使用批处理,
普通的执行过程是:每处理一条数据,就访问一次数据库;
而批处理是:累积到一定数量,再一次性提交到数据库,减少了与数据库的交互次数,所以效率会大大提高
至于事务:事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功,默认是关闭事务的。
更多事务的资料,请参考这里:http://blog.csdn.net/caomiao2006/article/details/22412755
1. PreparedStatement使用批处理 executeBatch()
1.1. 不使用executeBatch(),而使用executeUpdate()
代码如下:
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(dbUrl, user, password);
PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");
for(int i=0; i<10000; i++){
pstmt.setString(1, "abc"+i);
pstmt.setInt(2, id);
pstmt.executeUpdate();
}
这样,更新10000条数据,就得访问数据库10000次
1.2. 而使用executeBatch()
代码如下:
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(dbUrl, user, password);
PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");
for(int i=0; i<10000; i++){
pstmt.setString(1, "abc"+i);
pstmt.setInt(2, id);
pstmt.addBatch();//添加到同一个批处理中
}
pstmt.executeBatch();//执行批处理
注意:1. 如果使用了 addBatch() -> executeBatch() 还是很慢,那就得使用到这个参数了
rewriteBatchedStatements=true (启动批处理操作)
在数据库连接URL后面加上这个参数:
String dbUrl = "jdbc:mysql://localhost:3306/User? rewriteBatchedStatements=true";
2. 在代码中,pstmt的位置不能乱放,
//必须放在循环体外
pstmt = conn.prepareStatement("update content set introtext=? where id=?");
for(int i=0; i<10000; i++){
//放这里,批处理会执行不了,因为每次循环重新生成了pstmt,不是同一个了
//pstmt = conn.prepareStatement("update content set introtext=? where id=?");
pstmt.setString(1, "abc"+i);
pstmt.setInt(2, id);
pstmt.addBatch();//添加到同一个批处理中
}
pstmt.executeBatch();//执行批处理
2. 启用事务处理
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(dbUrl, user, password);
conn.setAutoCommit(false);//将自动提交关闭
PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");
pstmt.setString(1, tempintrotext);
pstmt.setInt(2, id);
pstmt.addBatch();
pstmt.executeBatch();
pstmt.close();
conn.commit();//执行完后,手动提交事务
conn.setAutoCommit(true);//再把自动提交打开,避免影响其他需要自动提交的操作
conn.close();
3. 事务和批处理混合使用
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(dbUrl, user, password);
conn.setAutoCommit(false);//将自动提交关闭
PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");
for(int i=0; i<1000000; i++){
pstmt.setString(1, tempintrotext);
pstmt.setInt(2, id);
pstmt.addBatch();
//每500条执行一次,避免内存不够的情况,可参考,Eclipse设置JVM的内存参数
if(i>0 && i%500==0){
pstmt.executeBatch();
//如果不想出错后,完全没保留数据,则可以每执行一次提交一次,但得保证数据不会重复
conn.commit();
}
}
pstmt.executeBatch();//执行最后剩下不够500条的
pstmt.close();
conn.commit();//执行完后,手动提交事务
conn.setAutoCommit(true);//再把自动提交打开,避免影响其他需要自动提交的操作
conn.close();
较完整的代码:
public class ExecuteBatchTest {
private Connection conn;
private PreparedStatement pstmt;
private PreparedStatement pstmt2;
private ResultSet rs;
private String user = "root";
private String password = "123456";
private String dbUrl = "jdbc:mysql://localhost:3306/user?rewriteBatchedStatements=true";
private int limitNum = 10000;
public void changeData() {
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(dbUrl, user, password);
//既不用batch,也不用事务
testBatch(false,false);
//只用batch, 不用事务
testBatch(false,true);
//只用事务,不用batch
testBatch(true,false);
//不仅用事务,还用batch
testBatch(true,true);
pstmt.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void testBatch(Boolean openTransaction, Boolean useBatch) throws SQLException{
if(openTransaction)
conn.setAutoCommit(false);
if(pstmt!=null){
pstmt.clearParameters();
pstmt.clearBatch();
}
pstmt = conn.prepareStatement("insert into person (name) values (?)");
long start = System.currentTimeMillis();
for(int a = 0;a<limitNum;a++){
String name = "tommy"+a;
pstmt.setString(1, name);
if(useBatch)
pstmt.addBatch();
else
pstmt.executeUpdate();
}
if(useBatch)
pstmt.executeBatch();
if(openTransaction){
conn.commit();
conn.setAutoCommit(true);
}
long end = System.currentTimeMillis();
System.out.println("use time:"+(end-start)+" ms");
}
//main method
publi static void main(String[] args){
ExecuteBatchTest ebt = new ExecuteBatchTest();
ebt.changeData();
}
}
运行结果:

分别是: 不用批处理,不用事务;
只用批处理,不用事务;
只用事务,不用批处理;
既用事务,也用批处理;(很明显,这个最快,所以建议在处理大批量的数据时,同时使用批处理和事务)
JDBC的PreparedStatement启动事务使用批处理executeBatch()的更多相关文章
- JDBC批处理executeBatch
JDBC运行SQL声明,有两个处理接口,一PreparedStatement,Statement,一般程序JDBC有多少仍然比较PreparedStatement 只要运行批处理,PreparedSt ...
- java中使用JDBC的preparedStatement批处理数据的添加
在项目中我们偶尔可能会遇到批量向数据库中导入数据,如果批处理的情况较多的情况下可以使用spring batch,如果只是一个导入功能的话可以考虑使用jdbc的preparedStatement处理. ...
- JDBC之PreparedStatement
JDBC之PreparedStatement 一.java.sql.PreparedStatement接口简介 该接口表示预编译的 SQL 语句的对象. SQL 语句被预编译并存储在 Prepared ...
- JDBC&&c3p0、事务、批处理、多线程 于一体的经典秘方QueryRunner
目录: 基础篇_功能各自回顾 JDBC基础代码回顾(使用JdbcUtils工具简化) c3p0数据库连接池的使用(使用JdbcUtils工具简化) 大数据的插入(使用c3p0+JdbcUtils工具简 ...
- JDBC 中preparedStatement和Statement区别
一.概念 PreparedStatement是用来执行SQL查询语句的API之一,Java提供了 Statement.PreparedStatement 和 CallableStatement三种方式 ...
- JDBC入门(4)--- 批处理
1.Statement批处理 当你有10条SQL语句要执行时,一次向服务器发送一条SQL语句,这样做的效率上极差,处理的方案是使用批处理,即一次向服务发送多条SQL语句,然后由服务器一次性处理. 批处 ...
- JDBC 中的事务和批处理 batch
JDBC事务处理: 事务处理一般在事务开始前把事务提交设置为false 所有DML语句执行完成后提交事务 demo: package com.xzlf.jdbc; import java.sql.Co ...
- jdbc java数据库连接 10)批处理
批处理 很多时候,需要批量执行sql语句! 需求:批量保存信息! 设计: AdminDao Public void save(List<Admin list){ // 目前用这种方式 ...
- jdbc、事务(Transaction)、批处理 回顾
论文写的头疼,回顾一下jdbc,换换脑子 传统的写法: 1.加载驱动类 class.forname("jdbc类的包结构"); 2.获得连接 Connection conn=Dri ...
随机推荐
- opencv3.3.1+vs2015+c++实现直接在图像上画掩码,保存掩码图片
左键红右键蓝,保存为k #include "opencv2\imgproc\imgproc.hpp" // Gaussian Blur #include "opencv2 ...
- Socket 简易静态服务器 WPF MVVM模式(一)
整体代码下载 主要实现功能: Socket的简单应用 可修改IP和端口 显示来访信息 界面设计: 界面采用MVVM设计,很简陋. 前台的主要目的是 输入IP地址 输入端口 输入文件目录 开启监听和停止 ...
- vs引入资源
把资源放在程序目录中,然后点击显示所有文件,然后在资源上右键“包括在项目中”
- spring 学习(二):spring bean 管理--配置文件和注解混合使用
spring 学习(二)spring bean 管理--配置文件和注解混合使用 相似的,创建 maven 工程,配置pom.xml 文件,具体可以参考上一篇博文: sprint 学习(一) 然后我们在 ...
- luoguP3648 [APIO2014]序列分割
https://www.luogu.org/problemnew/show/P3648 同bzoj3675 这题斜率优化+滚动数组就可以了qwq 因为我是在飞机上瞎bb的式子,所以可能会和别的题解的式 ...
- 洛谷P1251 餐巾计划问题(费用流)
传送门 不得不说这题真是思路清奇,真是网络流的一道好题,完全没想到网络流的建图还可以这么建 我们把每一个点拆成两个点,分别表示白天和晚上,白天可以得到干净的餐巾(购买的,慢洗的,快洗的),晚上可以得到 ...
- LAMP课程(3)
LAMP课程(3) 一.bash的使用 1.1.输出重定向 >:覆盖输出(写入内容) 具体实例1:将内容写入到文件中 >>:追加输出 具体实例2: 1.2 && ...
- Ping命令简单报错介绍
了解ABC类IP地址:网络.主机.子网.广播. ---------------------------- 学会ping: ping www.baidu.com 网络检测:ping某一主机可以正常启动! ...
- 5.EM
- 《Andrew Ng深度学习》笔记4
浅层神经网络 1.激活函数 在神经网络中,激活函数有很多种,常用的有sigmoid()函数,tanh()函数,ReLu函数(修正单元函数),泄露ReLu(泄露修正单元函数).它们的图形如下: sigm ...