您可以通过PreparedStatement#addBatch()创build一个批处理,并通过PreparedStatement#executeBatch()执行它。
这是一个开球的例子:
public void save(List entities) throws SQLException { try ( Connection connection = database.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL_INSERT); ) { int i = 0; for (Entity entity : entities) { statement.setString(1, entity.getSomeProperty()); // ... statement.addBatch(); i++; if (i % 1000 == 0 || i == entities.size()) { statement.executeBatch(); // Execute every 1000 items. } } } }
每1000个项目执行一次,因为一些JDBC驱动程序和/或DB可能会限制批处理长度。
另见 :
JDBC教程 – 使用PreparedStatement
JDBC教程 – 使用Statement对象进行批量更新
当使用MySQL驱动程序时,必须将连接参数rewriteBatchedStatements设置为true(jdbc:mysql:// localhost:3306 / TestDB? rewriteBatchedStatements = true )。
使用这个参数,当表被locking一次,索引只更新一次时,语句将被重写为批量插入。 所以它快得多。
如果没有这个参数,只能使用更简洁的源代码。
如果您可以dynamic创build您的SQL语句,您可以执行以下解决方法:
String myArray[][] = { { "1-1", "1-2" }, { "2-1", "2-2" }, { "3-1", "3-2" } }; StringBuffer mySql = new StringBuffer( "insert into MyTable (col1, col2) values (?, ?)"); for (int i = 0; i < myArray.length - 1; i++) { mySql.append(", (?, ?)"); } myStatement = myConnection.prepareStatement(mySql.toString()); for (int i = 0; i < myArray.length; i++) { myStatement.setString(i, myArray[i][1]); myStatement.setString(i, myArray[i][2]); } myStatement.executeUpdate();
如果你在表中有自动增量,并且需要访问它,你可以使用下面的方法…在使用之前做testing,因为语句中的getGeneratedKeys(),因为它取决于所使用的驱动程序。 以下代码在Maria DB 10.0.12和Maria JDBC驱动程序1.2上进行了testing
请记住,增加批量大小只会在一定程度上提高性能……对于我的设置,将批量增加到500以上实际上会降低性能。
public Connection getConnection(boolean autoCommit) throws SQLException { Connection conn = dataSource.getConnection(); conn.setAutoCommit(autoCommit); return conn; } private void testBatchInsert(int count, int maxBatchSize) { String querySql = "insert into batch_test(keyword) values(?)"; try { Connection connection = getConnection(false); PreparedStatement pstmt = null; ResultSet rs = null; boolean success = true; int[] executeResult = null; try { pstmt = connection.prepareStatement(querySql, Statement.RETURN_GENERATED_KEYS); for (int i = 0; i < count; i++) { pstmt.setString(1, UUID.randomUUID().toString()); pstmt.addBatch(); if ((i + 1) % maxBatchSize == 0 || (i + 1) == count) { executeResult = pstmt.executeBatch(); } } ResultSet ids = pstmt.getGeneratedKeys(); for (int i = 0; i < executeResult.length; i++) { ids.next(); if (executeResult[i] == 1) { System.out.println("Execute Result: " + i + ", Update Count: " + executeResult[i] + ", id: " + ids.getLong(1)); } } } catch (Exception e) { e.printStackTrace(); success = false; } finally { if (rs != null) { rs.close(); } if (pstmt != null) { pstmt.close(); } if (connection != null) { if (success) { connection.commit(); } else { connection.rollback(); } connection.close(); } } } catch (SQLException e) { e.printStackTrace(); } }
@Ali Shakiba你的代码需要一些修改。 错误部分:
for (int i = 0; i < myArray.length; i++) { myStatement.setString(i, myArray[i][1]); myStatement.setString(i, myArray[i][2]); }
更新的代码:
String myArray[][] = { {"1-1", "1-2"}, {"2-1", "2-2"}, {"3-1", "3-2"} }; StringBuffer mySql = new StringBuffer("insert into MyTable (col1, col2) values (?, ?)"); for (int i = 0; i < myArray.length - 1; i++) { mySql.append(", (?, ?)"); } mysql.append(";"); //also add the terminator at the end of sql statement myStatement = myConnection.prepareStatement(mySql.toString()); for (int i = 0; i < myArray.length; i++) { myStatement.setString((2 * i) + 1, myArray[i][1]); myStatement.setString((2 * i) + 2, myArray[i][2]); } myStatement.executeUpdate();
我们可以在JDBC中一起提交多个更新来提交批量更新。
我们可以使用Statement,PreparedStatement和CallableStatement对象进行bacth更新,并禁用自动提交
addBatch()和executeBatch()函数与所有语句对象一起提供BatchUpdate
这里addBatch()方法将一组语句或参数添加到当前批处理中。