JDBC批处理插入更新示例

时间:2020-01-09 10:35:22  来源:igfitidea点击:

在本教程中,我们将看到如何使用JDBC批处理进行批处理插入或者更新。如果我们必须运行大量的SQL语句,则将它们作为批处理而不是作为单个命令访问每个命令的DB效率更高。

JDBC中批处理的方法

在JDBC Statement界面中,有以下方法可用于批量支持

  • addBatch(String sql)–将给定的SQL命令添加到此Statement对象要批量执行的SQL命令列表中。
  • clearBatch()–清空此Statement对象的当前SQL命令列表。
  • executeBatch()–将一批命令提交给数据库以执行,如果所有命令成功执行,则返回更新计数数组。

在PreparedStatement中,还有另一种方法

  • addBatch()–将参数化的SQL添加到要批量执行的命令列表中。

JDBC批量插入示例

在此批量插入示例中,我们将使用PreparedSatement将记录插入Employee表中,DB是MySQL。

在MySQL中,我们必须在连接字符串中添加rewriteBatchedStatements = true,以便在调用executeBatch()时将为INSERT准备的语句重写为多值插入。

因此,添加到批处理中的查询就像单个查询一样

插入TABLE_NAME(COL1,COL2)值(" val1"," val2")
插入TABLE_NAME(COL1,COL2)值(" val3"," val4")
插入TABLE_NAME(COL1,COL2)值(" val5"," val6")

被转换为多值插入

插入TABLE_NAME(COL1,COL2)值(" val1"," val2"),(" val3"," val4"),(" val5"," val6")

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JDBCBatchDemo {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Load driver
      Class.forName("com.mysql.cj.jdbc.Driver");
      // connection object
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/theitroad?rewriteBatchedStatements=true", 
        "root", "admin");
      String insertSQL = "INSERT INTO EMPLOYEE (FIRST_NAME, LAST_NAME, DEPARTMENT) values (?, ?, ?)";
      int batchSize = 5;
      // create Statement object
      PreparedStatement preparedStatement = connection.prepareStatement(insertSQL);
      for(int i = 1; i <= 10; i++){
        preparedStatement.setString(1, "TestName"+i);               
        preparedStatement.setString(2, "LName"+i);
        preparedStatement.setString(3, "Dept");
        // Keep adding to batch
        preparedStatement.addBatch();
        // Execute batch in chunks
        if(i%batchSize == 0){
          preparedStatement.executeBatch();
        }
      }
      // For the left over records
      preparedStatement.executeBatch();  

    } catch (ClassNotFoundException | SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      if(connection != null){         
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } 
    }	      	     
  }
}

在程序中,要注意的一些重要点是:

  • URL中是否使用rewriteBatchedStatements = true-jdbc:mysql:// localhost:3306 / theitroad?rewriteBatchedStatements = true
  • 在该程序中,总共5条记录中插入了10条记录。一个好主意是将较小的批处理大批量地分割并执行。例如,假设我们正在运行一批1000个插入,而不是一次将所有1000条记录发送到DB,则最好执行100条记录的批次。
  • 如果批处理更新中的命令之一无法正确执行,则executeBatch()方法将引发BatchUpdateException,并且JDBC驱动程序可能会或者可能不会继续处理批处理中的其余命令。
  • 在MySQL DB中,如果抛出BatchUpdateException,则不处理该批处理中的其余命令,但是将保留在异常之前所做的更改(如果已执行executeBatch()命令)。例如,如果我们正在为5条记录的块执行批处理,并且第7条insert语句引发异常,则已处理的记录1-5将保留。如果要回滚所有更改,则应在事务中批量运行。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JDBCBatchDemo {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Load driver
      Class.forName("com.mysql.cj.jdbc.Driver");
      // connection object
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/theitroad?rewriteBatchedStatements=true", 
        "root", "admin");
      connection.setAutoCommit(false);
      String insertSQL = "INSERT INTO EMPLOYEE (FIRST_NAME, LAST_NAME, DEPARTMENT) values (?, ?, ?)";
      int batchSize = 5;
      // create Statement object
      PreparedStatement preparedStatement = connection.prepareStatement(insertSQL);
      for(int i = 1; i <= 10; i++){
        preparedStatement.setString(1, "TestName"+i);    
        preparedStatement.setString(2, "LName"+i);        
        preparedStatement.setString(3, "Dept");
        // Keep adding to batch
        preparedStatement.addBatch();
        // Execute batch in chunks
        if(i%batchSize == 0){
          preparedStatement.executeBatch();
        }
      }
      // For the left over records
      preparedStatement.executeBatch();  
      connection.commit();

    } catch (ClassNotFoundException | SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      if(connection != null){         
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } 
    }	      	     
  }
}