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(); } } } } }