Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.
Cómo escribir en masa con transacción y bulkInsert
Propósito. Insertar/actualizar muchas filas con alto rendimiento. Sin transacción, cada INSERT se convierte en un commit en disco (lento). Hay tres niveles: (1) envolver todo en transaction(...), (2) reutilizar un SqliteStmt con reset(), (3) usar bulkInsert, que hace el loop bind/step/reset en código nativo (más rápido).
APIs usadas
SqliteDb.transaction(Runnable body)— ejecutabodydentro deBEGIN/COMMIT; haceROLLBACKautomático sibodylanzaRuntimeException(y la relanza). Forma recomendada para atomicidad.SqliteDb.begin()/commit()/rollback()— control manual de la transacción (equivalen aexec("BEGIN"/"COMMIT"/"ROLLBACK")). Prefieretransaction(...)para no olvidar el rollback.SqliteDb.prepare(String sql)— prepara unSqliteStmtreutilizable (compila una vez). Debes cerrarlo (try-with-resources).SqliteStmt.bindInt/bindLong/bindDouble/bindString/bindBlob/bindNull(idx, v)ybindAll(Object...)— bind 1-based; retornanthis(fluido).step()ejecuta;reset()prepara para la próxima ejecución (mantiene los binds; usaclearBindings()si quieres reiniciarlos).SqliteDb.bulkInsert(String sql, List<Object[]> rows)— preparasqluna vez y lo ejecuta para cadaObject[]dentro de una única transacción, en loop nativo. Retorna el nº de filas procesadas. CadaObject[]tiene un elemento por parámetro?; tipos aceptados:Long/Integer,Double/Float,String,byte[],null. Los tipos de columna se infieren de la PRIMERA fila — mantén las filas homogéneas. Alias:bulkUpdate,bulkDelete.
¿Por qué reutilizar el statement?
preparecompila el SQL; repetirprepareen cada fila recompila. Reutilizar conreset()compila una vez y solo re-vincula — mucho más rápido en loops grandes.
Ejemplo completo (copiar, pegar y ejecutar)
package com.exemplo;
import java.util.*; // List, ArrayList
import dev.crossfly.ui.*; // Window
import dev.crossfly.ui.layout.*; // VerticalLayout
import dev.crossfly.sqlite.*; // SqliteDb, SqliteStmt
/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
try (SqliteDb db = SqliteDb.open("app.db"))
{
db.exec("CREATE TABLE IF NOT EXISTS t(a INTEGER, b TEXT)");
// Opción A — transacción + statement reutilizado (reset entre ejecuciones)
db.transaction(() ->
{
try (SqliteStmt st = db.prepare("INSERT INTO t(a, b) VALUES(?, ?)"))
{
for (int i = 0; i < 10_000; i++)
{
st.bindInt(1, i) // idx 1-based
.bindString(2, "row" + i)
.step();
st.reset(); // listo para la siguiente fila
}
}
}); // commit automático; rollback automático si lanza
// Opción B — bulkInsert nativo (el más rápido para grandes volúmenes)
List<Object[]> rows = new ArrayList<>();
for (int i = 0; i < 10_000; i++)
rows.add(new Object[]{ i, "row" + i }); // tipos inferidos de la 1ª fila
int n = db.bulkInsert("INSERT INTO t(a, b) VALUES(?, ?)", rows);
System.out.println(n + " linhas inseridas");
}
}
}
El fragmento de abajo muestra solo el núcleo. Para ejecutarlo, colócalo en el esqueleto
MainWindowde arriba.
Fragmento mínimo
// verificado en la fuente: transaction, prepare + bind (1-based) + step + reset, bulkInsert
import dev.crossfly.sqlite.*;
import java.util.*;
try (SqliteDb db = SqliteDb.open("app.db"))
{
db.exec("CREATE TABLE IF NOT EXISTS t(a INTEGER, b TEXT)");
// Opción A — transacción + statement reutilizado (reset entre ejecuciones)
db.transaction(() ->
{
try (SqliteStmt st = db.prepare("INSERT INTO t(a, b) VALUES(?, ?)"))
{
for (int i = 0; i < 10_000; i++)
{
st.bindInt(1, i) // idx 1-based
.bindString(2, "row" + i)
.step();
st.reset(); // listo para la siguiente fila
}
}
}); // commit automático; rollback automático si lanza
// Opción B — bulkInsert nativo (el más rápido para grandes volúmenes)
List<Object[]> rows = new ArrayList<>();
for (int i = 0; i < 10_000; i++)
rows.add(new Object[]{ i, "row" + i }); // tipos inferidos de la 1ª fila
int n = db.bulkInsert("INSERT INTO t(a, b) VALUES(?, ?)", rows);
System.out.println(n + " linhas inseridas");
}
Profundiza
- Trabajo en background · Rendimiento y listas grandes
- Recetas hermanas: CRUD parametrizado · Uso fuera de la paint thread
¿Te resultó útil esta página?¡Gracias por tu opinión!