JDBC insert multiple rows
In case that your records size is less than or equal to 1000 the following code is better than both of your codes:
StringBuilder query = new StringBuilder("INSERT INTO table (id, name, value) VALUES ");
if (records.size() <= 1000) {
for (int i = 0; i < records.size(); i++)
query.append("(?, ?, ?), ");
query = new StringBuilder(query.substring(1, query.length() - 1));
PreparedStatement ps = connection.prepareStatement(query.toString());
for (int i = 0; i < records.size(); i++) {
ps.setInt((i * 3) + 1, record.id);
ps.setString((i * 3) + 2, record.name);
ps.setInt((i * 3) + 3, record.value);
}
ps.executeUpdate();
}
In this way you are using PreparedStatement and create it dynamically depending the size of your record list using multiple values clause in one insert query
First of all, with query string concatenation you not only lose the type conversion native to PreparedStatement methods, but you also get vulnerable to malicious code being executed in the database.
Second, PreparedStatements are previously cached in the very database itself, and this already gives a very good performance improvement over plain Statements.
You can face a serious performance issue if the number of items that you want to insert is large. Therefore, it is safer to define a batch size, and constantly execute the query when the batch size is reached.
Something like the following example code should work. For the full story of how using this code efficiently, please see this link.
private static void insertList2DB(List<String> list) {
final int batchSize = 1000; //Batch size is important.
Connection conn = getConnection();
PreparedStatement ps = null;
try {
String sql = "INSERT INTO theTable (aColumn) VALUES (?)";
ps = conn.prepareStatement(sql);
int insertCount=0;
for (String item : list) {
ps.setString(1, item);
ps.addBatch();
if (++insertCount % batchSize == 0) {
ps.executeBatch();
}
}
ps.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
System.exit(1);
}
finally {
try {
ps.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Turn off autocommit
executeBatch
will have an improved performance over executeUpdate
as long as autocommit is set to false:
connection.setAutoCommit(false);
PreparedStatement ps = connection.prepareStatement(query);
for (Record record : records) {
// etc.
ps.addBatch();
}
ps.executeBatch();
connection.commit();