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()的更多相关文章

  1. JDBC批处理executeBatch

    JDBC运行SQL声明,有两个处理接口,一PreparedStatement,Statement,一般程序JDBC有多少仍然比较PreparedStatement 只要运行批处理,PreparedSt ...

  2. java中使用JDBC的preparedStatement批处理数据的添加

    在项目中我们偶尔可能会遇到批量向数据库中导入数据,如果批处理的情况较多的情况下可以使用spring batch,如果只是一个导入功能的话可以考虑使用jdbc的preparedStatement处理. ...

  3. JDBC之PreparedStatement

    JDBC之PreparedStatement 一.java.sql.PreparedStatement接口简介 该接口表示预编译的 SQL 语句的对象. SQL 语句被预编译并存储在 Prepared ...

  4. JDBC&&c3p0、事务、批处理、多线程 于一体的经典秘方QueryRunner

    目录: 基础篇_功能各自回顾 JDBC基础代码回顾(使用JdbcUtils工具简化) c3p0数据库连接池的使用(使用JdbcUtils工具简化) 大数据的插入(使用c3p0+JdbcUtils工具简 ...

  5. JDBC 中preparedStatement和Statement区别

    一.概念 PreparedStatement是用来执行SQL查询语句的API之一,Java提供了 Statement.PreparedStatement 和 CallableStatement三种方式 ...

  6. JDBC入门(4)--- 批处理

    1.Statement批处理 当你有10条SQL语句要执行时,一次向服务器发送一条SQL语句,这样做的效率上极差,处理的方案是使用批处理,即一次向服务发送多条SQL语句,然后由服务器一次性处理. 批处 ...

  7. JDBC 中的事务和批处理 batch

    JDBC事务处理: 事务处理一般在事务开始前把事务提交设置为false 所有DML语句执行完成后提交事务 demo: package com.xzlf.jdbc; import java.sql.Co ...

  8. jdbc java数据库连接 10)批处理

    批处理 很多时候,需要批量执行sql语句! 需求:批量保存信息! 设计: AdminDao Public  void  save(List<Admin list){    // 目前用这种方式 ...

  9. jdbc、事务(Transaction)、批处理 回顾

    论文写的头疼,回顾一下jdbc,换换脑子 传统的写法: 1.加载驱动类 class.forname("jdbc类的包结构"); 2.获得连接 Connection conn=Dri ...

随机推荐

  1. duilib入门简明教程 -- 自绘标题栏(5)

       如果大家有做过标题栏的自绘,肯定会感慨各种不容易,并且现有的一些资料虽然完美的实现了功能,但是代码比较乱,需要自行整理.如果用duilib,就是小case啦.     duilib其实并没有区分 ...

  2. perationalError: (2003, "Can't connect to MySQL server on u'192.168.1.6' (timed out)")

    在Ubuntu(192.168.1.20)中部署项目后,mysql还在另外一台windows(192.168.1.6)机子上,ping windows时可以ping通,但是访问项目提示: perati ...

  3. 执行存储过程比即时SQL执行慢的解决方案

    发生过这样一件事, 写了一个SQL,查询数据大概5秒,但是放到存储过程里面去了过后,查了5分钟也没给出结果,后来网上找解决方案,终于找到一个解决方案. 在存储过程的参数那里对参数进行一个传递.反正他们 ...

  4. Kotlin when 流程判断

    如果学过C或者java C#等语言. 一定熟悉SWITCH这个流程判断 但是在kotlin中却没有这个.而是 使用了When来代替. 当什么时候. 下面我觉一个简单的例子: import java.u ...

  5. tcp连接过程中的三次握手和四次挥手

    在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手握手建立连接 @第一次握手: 建立连接是,客户端A发送SYN包到服务器B,并进入SYN_SEND状态,等待B确认. @第二次握手: 服务 ...

  6. Effective Java 3rd.Edition 翻译

    推荐序 前言 致谢 第一章 引言 第二章 创建和销毁对象 第1项:用静态工厂方法代替构造器 第2项:遇到多个构造器参数时要考虑使用构建器 第3项:用私有构造器或者枚举类型强化Singleton属性 第 ...

  7. 条目四《用empty来代替检查size()是否为0》

    条目四<用empty来代替检查size()是否为0> 首先先说结论: empty()实现为内联函数.(众所周知, 优秀的内联函数的效率比一般函数是高的) 在stl标准库中,empty()对 ...

  8. Ubuntu16.04更换下载源

    更新源的方法 进入/etc/apt/ cd /etc/apt 对 sources.list文件进行备份: sudo cp sources.list sources.list.bak 打开源列表文件 s ...

  9. Spring学习笔记(一)—— Spring介绍及入门案例

    一.Spring概述 1.1 Spring是什么 Spring是一个开源框架,是于2003年兴起的一个轻量级的Java开发框架, 由Rod Johnson 在其著作<Expert one on ...

  10. Mongodb服务的设置成window服务自启动

    服务安装bat:例子 cd D: D: cd "Program Files" cd MongoDB\Server\3.0\bin mongod -dbpath "F:\w ...