Lo típico en Java al trabajar con bases de datos, suele ser montar la sentencia de inserción y a continuación ejecutarla. Pero cuando se trata de muchos inserts sobre la misma tabla esto no es eficiente ya que se pierde demasiado tiempo en las llamadas a la base de datos. En estos casos es conveniente optimizar inserts masivos en el código Java.
Para realizar esto, la clase PreparedStatment contiene métodos para crear lotes (batch) de sentencias. De esta forma, en vez de lanzar cada sentencia, lo que se hace es ir añadiéndolas a un lote para luego lanzar todas las sentencias en una única llamada a la base de datos. Este PreparedStatment (depurando se puede ver), se guarda por un lado la sentencia con sus parámetros como interrogantes (?) y por otro un array de arrays con los valores de los parámetros en cada sentencia.
Ejemplo de cómo optimizar inserts masivos
Lo primero es crear la sentencia y la instancia de PreparedStatment a partir de la misma. Los valores del insert se definen aquí como interrogantes (?).
String sql = "INSERT INTO tabla (campo1, campo2, campo3) VALUES (?,?,?)"; PreparedStatement ps = con.prepareStatement(sql);
Lo siguiente será rellenar los valores de los parámetros, definiendo la posición y el valor, mediante los distintos métodos que proporciona PreparedStatment según el tipo de dato (.setDate, .setInt, .setLong, setString, etc.). Estos tipos deberán ser los mismos que los definidos en la tabla en el base de datos. Hay que tener en cuenta algunos detalles como que nos nulos se cargan con .setNull(…), donde el segundo parámetro será el tipo del campo (p.e.: java.sql.Types.INTEGER). En el caso de cargar una fecha, la fecha que hay que pasarle es de tipo java.sql.Date, por lo que si tenemos una java.util.Date, habrá que convertila: new java.sql.Date(fecha.getTime());
Una vez añadidos los parámetros, se añaden al lote con addBatch(). Este fragmento de código, habrá que replicarlo una vez por registro a insertar, por lo que es candidato a ir dentro de un bucle (for, foreach, etc.) que recorra la lista con los datos de los registros a insertar.
ps.setInt(1, 10); ps.setString(2,"valor2"); ps.setFloat(3, 120.56); ps.addBatch();
Una vez cargados todos los parámetros de todas las sentencias, ya se puede mandar a la base de datos el insert masivo. Además, es conveniente cerrar el PreparedStatment, sin olvidarnos de hacer commit para confirmar la transacción.
ps.executeBatch(); con.commit(); ps.close();