Я хочу вставить сразу несколько строк в таблицу MySQL с помощью Java. Количество строк динамическое. Раньше я делал ...
for (String element : array) {
myStatement.setString(1, element[0]);
myStatement.setString(2, element[1]);
myStatement.executeUpdate();
}
Я хотел бы оптимизировать это, чтобы использовать синтаксис, поддерживаемый MySQL:
INSERT INTO table (col1, col2) VALUES ('val1', 'val2'), ('val1', 'val2')[, ...]
но с a PreparedStatement
я не знаю, как это сделать, так как заранее не знаю, сколько элементов array
будет содержать. Если это невозможно с помощью PreparedStatement
, как еще я могу это сделать (и при этом избежать значений в массиве)?
java
mysql
jdbc
prepared-statement
batch-insert
Том Мартенал
источник
источник
connection.setAutoCommit(false);
иconnection.commit();
загрузите.oracle.comi == entities.size()
Когда используется драйвер MySQL, вы должны установить для параметра подключения
rewriteBatchedStatements
значение true( jdbc:mysql://localhost:3306/TestDB?**rewriteBatchedStatements=true**)
.С этим параметром оператор переписывается на массовую вставку, когда таблица блокируется только один раз, а индексы обновляются только один раз. Так что намного быстрее.
Без этого параметра единственным преимуществом является более чистый исходный код.
источник
5.1.45
версии разъема mysql.rewriteBatchedStatements=true
нет прироста производительности.Если вы можете создать свой оператор 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();
источник
Если у вас есть автоматическое приращение в таблице и вам нужно получить к ней доступ ... вы можете использовать следующий подход ... Проведите тест перед использованием, потому что getGeneratedKeys () в Statement, потому что это зависит от используемого драйвера. Приведенный ниже код протестирован на Maria DB 10.0.12 и драйвере Maria JDBC 1.2.
Помните, что увеличение размера пакета улучшает производительность только до определенной степени ... для моей установки увеличение размера пакета выше 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();
источник
myArray
длина превышает этот предел, вы столкнетесь с исключением. В моем случае у меня есть ограничение в 1000 строк, что вызывает необходимость пакетного выполнения, потому что я потенциально могу обновлять более 1000 строк при любом заданном запуске. Этот тип оператора теоретически должен работать нормально, если вы знаете, что вставляете меньше максимально допустимого. Что нужно иметь в виду.мы можем отправлять несколько обновлений вместе в JDBC для отправки пакетных обновлений.
мы можем использовать объекты Statement, PreparedStatement и CallableStatement для обновления bacth с отключением autocommit
Функции addBatch () и executeBatch () доступны со всеми объектами операторов для BatchUpdate.
здесь метод addBatch () добавляет набор операторов или параметров к текущему пакету.
источник