欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JDBC批处理sql

程序员文章站 2024-03-01 17:14:52
...

当需要成批插入或者更新记录时。可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。

JDBC的批量处理语句包括下面两个方法:

  • addBatch():添加需要批量处理的SQL语句或是参数;
  • executeBatch();执行批量处理语句;

 多条SQL语句的批量处理

JDBC批处理sql

一个SQL语句的批量传参

JDBC批处理sql

public void testBatch(){
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		String sql = null;
		
		try {
			connection = JDBCTools.getConnection();
			JDBCTools.beginTx(connection);
			sql = "INSERT INTO customers VALUES(?,?,?)";
			preparedStatement = connection.prepareStatement(sql);
			Date date = new Date(new java.util.Date().getTime());
			
			long begin = System.currentTimeMillis();
			for(int i = 0; i < 100000; i++){
				preparedStatement.setInt(1, i + 1);
				preparedStatement.setString(2, "name_" + i);
				preparedStatement.setDate(3, date);
				
				//"积攒" SQL 
				preparedStatement.addBatch();
				
				//当 "积攒" 到一定程度, 就统一的执行一次. 并且清空先前 "积攒" 的 SQL
				if((i + 1) % 300 == 0){
					preparedStatement.executeBatch();
					preparedStatement.clearBatch();
				}
			}
			
			//若总条数不是批量数值的整数倍, 则还需要再额外的执行一次. 
			if(100000 % 300 != 0){
				preparedStatement.executeBatch();
				preparedStatement.clearBatch();
			}
			
			long end = System.currentTimeMillis();
			
			System.out.println("Time: " + (end - begin)); //569
			
			JDBCTools.commit(connection);
		} catch (Exception e) {
			e.printStackTrace();
			JDBCTools.rollback(connection);
		} finally{
			JDBCTools.releaseDB(null, preparedStatement, connection);
		}
	}

JDBC实现批处理有两种方式:statement和preparedstatement

一、使用Statement完成批处理

  1、使用Statement对象添加要批量执行SQL语句,如下:

1 Statement.addBatch(sql1);
2 Statement.addBatch(sql2);
3 Statement.addBatch(sql3);

  2、执行批处理SQL语句:Statement.executeBatch();
  3、清除批处理命令:Statement.clearBatch();

1.1、使用Statement完成批处理范例

  1、编写测试的SQL脚本创建表

1  create table testbatch
2 (
3      id int primary key,
4      name varchar(20)
5 );

  2、编写测试代码,如下所示:



import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import me.gacl.utils.JdbcUtils;
import org.junit.Test;

public class JdbcBatchHandleByStatement {

    @Test
    public void testJdbcBatchHandleByStatement(){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql1 = "insert into testbatch(id,name) values(1,'aaa')";
            String sql2 = "insert into testbatch(id,name) values(2,'bbb')";
            String sql3 = "insert into testbatch(id,name) values(3,'CCC')";
            String sql4 = "insert into testbatch(id,name) values(4,'DDD')";
            String sql5 = "update testbatch set name='gacl' where id=1";
            String sql6 = "insert into testbatch(id,name) values(5,'FFF')";
            String sql7 = "delete from testbatch where id=2";
            st = conn.createStatement();
            //添加要批量执行的SQL
            st.addBatch(sql1);
            st.addBatch(sql2);
            st.addBatch(sql3);
            st.addBatch(sql4);
            st.addBatch(sql5);
            st.addBatch(sql6);
            st.addBatch(sql7);
            //执行批处理SQL语句
            st.executeBatch();
            //清除批处理命令
            st.clearBatch();
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
}


1.2、采用Statement.addBatch(sql)方式实现批处理的优缺点

  采用Statement.addBatch(sql)方式实现批处理:
    优点:可以向数据库发送多条不同的SQL语句。
    缺点:SQL语句没有预编译。
    当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。例如:

1 Insert into user(name,password) values('aa','111');
2 Insert into user(name,password) values('bb','222');
3 Insert into user(name,password) values('cc','333');
4 Insert into user(name,password) values('dd','444');

二、使用PreparedStatement完成批处理

2.1、使用PreparedStatement完成批处理范例

  测试代码如下:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import me.gacl.utils.JdbcUtils;
import org.junit.Test;
public class JdbcBatchHandleByPrepareStatement {
    public void testJdbcBatchHandleByPrepareStatement(){
        long starttime = System.currentTimeMillis();
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "insert into testbatch(id,name) values(?,?)";
            st = conn.prepareStatement(sql);
            for(int i=1;i<1000008;i++){  //i=1000  2000
                st.setInt(1, i);
                st.setString(2, "aa" + i);
                st.addBatch();
                if(i%1000==0){
                    st.executeBatch();
                    st.clearBatch();
                }
            }
            st.executeBatch();
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
        long endtime = System.currentTimeMillis();
        System.out.println("程序花费时间:" + (endtime-starttime)/1000 + "秒!!");
    }
}


2.2、采用PreparedStatement.addBatch()方式实现批处理的优缺点

  采用PreparedStatement.addBatch()实现批处理
    优点:发送的是预编译后的SQL语句,执行效率高。
    缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。


三种批处理的方法:

import lavasoft.common.DBToolkit; 
import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.SQLException; 
import java.sql.Statement; 
public class BatchExeSQLTest { 
        public static void main(String[] args) { 
                exeBatchStaticSQL(); 
        } 

        /** 
         * 批量执行预定义模式的SQL 
         */ 
        public static void exeBatchParparedSQL() { 
                Connection conn = null; 
                try { 
                        conn = DBToolkit.getConnection(); 
                        String sql = "insert into testdb.book (kind, name) values (?,?)"; 
                        PreparedStatement pstmt = conn.prepareStatement(sql); 
                        pstmt.setString(1, "java"); 
                        pstmt.setString(2, "jjjj"); 
                        pstmt.addBatch();                     //添加一次预定义参数 
                        pstmt.setString(1, "ccc"); 
                        pstmt.setString(2, "dddd"); 
                        pstmt.addBatch();                     //再添加一次预定义参数 
                        //批量执行预定义SQL 
                        pstmt.executeBatch(); 
                } catch (SQLException e) { 
                        e.printStackTrace(); 
                } finally { 
                        DBToolkit.closeConnection(conn); 
                } 
        } 

        /** 
         * 批量执行混合模式的SQL、有预定义的,还有静态的 
         */ 
        public static void exeBatchMixedSQL() { 
                Connection conn = null; 
                try { 
                        conn = DBToolkit.getConnection(); 
                        String sql = "insert into testdb.book (kind, name) values (?,?)"; 
                        PreparedStatement pstmt = conn.prepareStatement(sql); 
                        pstmt.setString(1, "java"); 
                        pstmt.setString(2, "jjjj"); 
                        pstmt.addBatch();    //添加一次预定义参数 
                        pstmt.setString(1, "ccc"); 
                        pstmt.setString(2, "dddd"); 
                        pstmt.addBatch();    //再添加一次预定义参数 
                        //添加一次静态SQL 
                        pstmt.addBatch("update testdb.book set kind = 'JAVA' where kind='java'"); 
                        //批量执行预定义SQL 
                        pstmt.executeBatch(); 
                } catch (SQLException e) { 
                        e.printStackTrace(); 
                } finally { 
                        DBToolkit.closeConnection(conn); 
                } 
        } 

        /** 
         * 执行批量静态的SQL 
         */ 
        public static void exeBatchStaticSQL() { 
                Connection conn = null; 
                try { 
                        conn = DBToolkit.getConnection(); 
                        Statement stmt = conn.createStatement(); 
                        //连续添加多条静态SQL 
                        stmt.addBatch("insert into testdb.book (kind, name) values ('java', 'java in aciton')"); 
                        stmt.addBatch("insert into testdb.book (kind, name) values ('c', 'c in aciton')"); 
                        stmt.addBatch("delete from testdb.book where kind ='C#'"); 
                        stmt.addBatch("update testdb.book set kind = 'JAVA' where kind='java'"); 
//                        stmt.addBatch("select count(*) from testdb.book");                //批量执行不支持Select语句 
                        //执行批量执行 
                        stmt.executeBatch(); 
                } catch (SQLException e) { 
                        e.printStackTrace(); 
                } finally { 
                        DBToolkit.closeConnection(conn); 
                } 
        } 
}