JDBC批处理分析

需要向数据库发送多条sql语句时, 为了提升执行效率, 可以考虑采用JDBC的批处理机制.

JDBC的批处理机制主要涉及Statement或PreparedStatement对象的以下方法:

|–addBatch(String sql) :Statement类的方法, 多次调用该方法可以将多条sql语句添加到Statement对象的命令列表中.

执行批处理时将一次性的把这些sql语句发送给数据库进行处理.

|–addBatch(): PreparedStatement类的方法, 多次调用该方法可以将多条预编译的sql语句添加到PreparedStatement对象的命令列表中.

执行批处理时将一次性的把这些sql语句发送给数据库进行处理.

|–executeBatch():把Statement对象或PreparedStatement对象命令列表中的所有sql语句发送给数据库进行处理.

|–clearBatch(): 清空当前sql命令列表.

[java] view plain copy
/* 
 * create table batch_test(id int primary key auto_increment, name varchar(40), age int); 
 */  
public class BatchTest {  
    @Test  
    public void statementBatch() {  
        Connection conn = null;  
        Statement st = null;  
        String sql_1 = "insert into batch_test(name, age) values('coolxing', 24)";  
        String sql_2 = "insert into batch_test(name, age) values('coolmin', 22)";  
        String sql_3 = "insert into batch_test(name, age) values('yong', 21)";  
        String sql_4 = "update batch_test set name='java' where id=1";  

        try {  
            conn = JdbcUtils.getConnection();  
            st = conn.createStatement();  
            st.addBatch(sql_1);  
            st.addBatch(sql_2);  
            st.addBatch(sql_3);  
            st.addBatch(sql_4);  
            st.executeBatch();  
            st.clearBatch();  
        } catch (SQLException e) {  
            e.printStackTrace();  
        } finally {  
            JdbcUtils.release(null, st, conn);  
        }  
    }  

    @Test  
    public void preparedStatementBatch() {  
        Connection conn = null;  
        PreparedStatement st = null;  
        String sql = "insert into batch_test(name, age) values(?, ?)";  

        try {  
            conn = JdbcUtils.getConnection();  
[java] view plain copy
            //通过只打开一个连接  
            st = conn.prepareStatement(sql);  
            for (int i = 0; i < 10002; i++) {  
                st.setString(1, "coolxing_" + i);  
                st.setInt(2, i);  
                st.addBatch();  
                // 需要防止Preparedstatement对象中的命令列表包含过多的待处理sql语句, 而造成outOfMemory错误  
                if (i % 500 == 0) {  
                    st.executeBatch();  
                    st.clearBatch();  
                }  
            }  
            // 将剩下的未处理命令发送给数据库  
            st.executeBatch();  
        } catch (SQLException e) {  
            e.printStackTrace();  
        } finally {  
            JdbcUtils.release(null, st, conn);  
        }  
    }  
}  

总结: 采用Statement.addBatch(sql)方式实现批处理可以向数据库发送不同类型的sql语句, 但是这些sql语句没有进行预编译, 执行效率不高. 且需要列出每一个sql语句. 而PreparedStatement.addBatch()只能应用在类型相同参数不同的sql语句中, 此种形式的批处理经常用于在同一个表中批量插入数据, 或批量更新表的数据.

注意不要一次性向命令列表中添加数量过多的sql语句, 防止出现outOfMemory错误.

原理分析:

前期的代码在与数据库进行通信时,都是先建立连接,建立连接花费的成本是最高的,然后发一个SQL语句,执行完后就关闭了连接。还有一个问题是发送的SQL语句都是通过网络传送的,比起本地调用来说,网络传输的成本也是高很多的。如果要插入或者更新一批数据进数据库,还是采用前期的方法,花费的时间会很多,给用户的感受会很慢。但是如果采用批处理,则在两个方便都会节约大部分成本,速度会更快。下面是批处理的示例代码:

   static void createBatch() throws SQLException {
          Connection conn = null;
          PreparedStatement ps = null;
          ResultSet rs = null;
          try {
              conn = JdbcUtils.getConnection();
              String sql = "insert into user(name,birthday, money) values (?, ?, ?) ";
              ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
              for (int i = 0; i < 100; i++) {
                  ps.setString(1, "batch name" + i);
                  ps.setDate(2, new Date(System.currentTimeMillis()));
                  ps.setFloat(3, 100f + i);

                  ps.addBatch();
              }
              int[] is = ps.executeBatch();
          } finally {
              JdbcUtils.free(rs, ps, conn);
          }
      }
如果不用批处理语句打包,则需要调用以前的create方法一百次,完成一百次数据库的连接和网络通讯。用批处理的方式,可以将100次插入打成一个包,然后一次性发给数据库,数据库执行完毕,返回结果。如果在两种方法调用上加上时间,就能够区分两者的速度差距了。但是并不是说用了批处理就一定比不用批处理要快,这根数据的版本、驱动的版本等都有很大关系。所以实际要用的时候,应该在环境上先测试一下两者的效果。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值