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 ...
随机推荐
- web集群时session同步的3种方法
在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,一个登录用户,一会是登录状态,一会又不是 ...
- sqlServer2008技术内幕笔记总结(实用的sql方法总结)
over函数的使用: 1.可以实现基于什么求和,省去group by: select xingming,xingbie,COUNT(*) over() as '总人数' from jbxx_xuesh ...
- [Win32::Console]Perl终端版生命游戏
环境,WinXP/Win7 Perl 5.16 默认循环1000次,按ESC提前退出 use strict; use Term::ReadKey; use Win32::Console; use T ...
- 【leetcode 94. 二叉树的中序遍历】解题报告
前往二叉树的:前序,中序,后序 遍历算法 方法一:递归 vector<int> res; vector<int> inorderTraversal(TreeNode* root ...
- SiriShortCut模型建立及数据交互逻辑
1.模型数据需求 意图: 手机号 密码 网关ID 打开该情景的命令 情景号 情景名 情景背景图 添加该意图时的 token值 主程序登陆共享数据 手机号 token值 2.操作逻辑 1.意图被唤起 获 ...
- 后置处理器----JSON提取器
JSON提取器可以很方便的让你从JSON响应格式中提取数据. 1)Name:JSON提取器的名称. 2)Apply to:应用范围,有些采样器还嵌套子采样器,可以在此处设置JSON提取器是作用与主采样 ...
- php代码审计2全局变量和超全局变量
全局变量:就是在函数外面定义的变量,不能在函数中直接使用,因为它的作用域不会到函数内部,所以在函数内部使用的时候尝尝看到类似global $a; 超全局变量:在所有脚本都有效,所以,在函数可以直接使用 ...
- BeanShell Processor_使用Java处理脚本
版权声明:本文为博主原创文章,未经博主允许不得转载. [try-catch] 建议使用Try----Catch块,这样Java语句出现问题时,日志更清晰: try { //java代码 } catch ...
- python 中文件夹的操作
文件有两个管家属性:路径和文件名. 路径指明了文件在磁盘的位置,文件名原点的后面部分称为扩展名(后缀),它指明了文件的类型. 一:文件夹操作 Python中os 模块可以处理文件夹 1,当前工作目录 ...
- SpringBoot设置默认启动页的2种方式
方式一: 继承WebMvcConfigurerAdapter,重写addViewControllers. @Configurationpublic class WebConfigurer extend ...