preparedstatement parametros insertar funciona ejemplo desde datos consultas con como java mysql jdbc prepared-statement batch-insert

parametros - preparedstatement java insert



Java: inserte varias filas en MySQL con PreparedStatement (6)

@Ali Shakiba su código necesita algunas modificaciones. Parte de error:

for (int i = 0; i < myArray.length; i++) { myStatement.setString(i, myArray[i][1]); myStatement.setString(i, myArray[i][2]); }

Código actualizado:

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

Quiero insertar varias filas en una tabla MySQL a la vez usando Java. El número de filas es dinámico. En el pasado yo estaba haciendo ...

for (String element : array) { myStatement.setString(1, element[0]); myStatement.setString(2, element[1]); myStatement.executeUpdate(); }

Me gustaría optimizar esto para usar la sintaxis soportada por MySQL:

INSERT INTO table (col1, col2) VALUES (''val1'', ''val2''), (''val1'', ''val2'')[, ...]

pero con un PreparedStatement no conozco ninguna forma de hacerlo ya que no sé de antemano cuántos elementos contendrá el conjunto. Si no es posible con un Estado PreparedStatement , ¿de qué otro modo puedo hacerlo (y aún así escapar de los valores del conjunto)?


Cuando se utiliza el controlador MySQL, debe establecer la conexión param rewriteBatchedStatements en true (jdbc: mysql: // localhost: 3306 / TestDB? RewriteBatchedStatements = true ).

Con este parámetro, la instrucción se reescribe en la inserción masiva cuando la tabla se bloquea solo una vez y los índices se actualizan solo una vez. Entonces es mucho más rápido.

Sin este parámetro, la única ventaja es un código fuente más limpio.


En caso de que tenga un incremento automático en la tabla y necesite acceder a él, puede usar el siguiente enfoque ... Haga una prueba antes de usar porque getGeneratedKeys () en Statement porque depende del controlador utilizado. El código siguiente se prueba en Maria DB 10.0.12 y Maria JDBC driver 1.2

Recuerde que aumentar el tamaño del lote mejora el rendimiento solo hasta cierto punto ... para mi configuración, aumentar el tamaño del lote por encima de 500 en realidad estaba degradando el rendimiento.

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


Puede crear un lote mediante PreparedStatement#addBatch() y ejecutarlo mediante PreparedStatement#executeBatch() .

Aquí hay un ejemplo de inicio:

public void save(List<Entity> 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. } } } }

Se ejecuta cada 1000 elementos porque algunos controladores JDBC y / o DB pueden tener una limitación en la duración del lote.

Ver también :


Si puede crear su instrucción sql dinámicamente, puede hacer la siguiente solución alternativa:

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


podemos enviar múltiples actualizaciones juntas en JDBC para enviar actualizaciones por lotes.

podemos usar los objetos Statement, PreparedStatement y CallableStatement para actualizar bacth con disable autocommit

Las funciones addBatch () y executeBatch () están disponibles con todos los objetos de declaración para tener BatchUpdate.

aquí el método addBatch () agrega un conjunto de declaraciones o parámetros al lote actual.