Description:
If you execute batched inserts with rewriteBatchedStatements=true set on the connection, then the array of row counts returned is incorrect. For a successful insert, the row count should always be 1. In PreparedStatement#executeBatchInserts(int), it is updating the row count array using the contents of updateCountRunningTotal, which is incorrect.
The problem here is that when the MySQL JDBC connector is used with Hibernate, the row counts returns from executeBatch are validated, which causes problems.
The short term workaround is to turn off rewriteBatchStatements, but this has undesirable performance implications.
How to repeat:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test {
private final static String CONNECTION_STRING = "jdbc:mysql://localhost:3306/xxx?rewriteBatchedStatements=true";
private final static String USER = "xxx";
private final static String PASSWORD = "xxx";
private final static String SQL = "insert into t1 (id, x) values (?, ?)";
private final static int BATCH_SIZE = 20;
public static void main(String[] args) throws SQLException {
Connection connection = DriverManager.getConnection(CONNECTION_STRING, USER, PASSWORD);
connection.setAutoCommit(false);
PreparedStatement ps = connection.prepareStatement(SQL);
for (int i = 0; i < BATCH_SIZE; i++) {
ps.setInt(1, i);
ps.setInt(2, 42);
ps.addBatch();
}
int[] rowCounts = ps.executeBatch();
for (int i = 0; i < BATCH_SIZE; i++) {
assert rowCounts[i] == 1;
}
}
}
Suggested fix:
In com.mysql.jdbc.PreparedStatement#executeBatchedInserts, set each element of the result to 1 instead of updateCountRunningTotal.