Como fazer CRUD parametrizado no SQLite
Propósito. Executar INSERT/UPDATE/DELETE e SELECT com parâmetros posicionais (?), evitando concatenação de strings (que causa SQL injection e erros de aspas). Atenção às duas convenções de índice do CrossFly.
⚠️ Índices. Ao bindar parâmetros, os índices são 1-based (
?nº 1, 2, …). Ao ler colunas do cursor, os índices são 0-based (getString(0)= primeira coluna). Isso é intencional e espelha a API nativa do SQLite.
APIs usadas
SqliteDb.execute(String sql, Object... params)— prepara, fazbindAll(params)(bind 1-based), executa um único INSERT/UPDATE/DELETE e retorna o nº de linhas afetadas (int). Os tipos são inferidos:Integer/Long/Short/Byte→inteiro,Float/Double→real,Boolean→0/1,byte[]→BLOB,null→NULL, senãotoString()→TEXT.SqliteDb.query(String sql, Object... params)— retorna umSqliteCursoraberto (bind 1-based). O chamador deve fechar (usetry-with-resources).SqliteCursor.next()— avança para a próxima linha; retornatruese houver linha.SqliteCursor.getInt(col)/getLong/getDouble/getString/getBlob/isNull(col)— getters tipados, coluna 0-based.SqliteDb.queryLong(sql, defaultValue, params)— atalho: 1ª coluna da 1ª linha comolong, oudefaultValuese não houver linhas.SqliteDb.queryString(sql, params)— atalho: 1ª coluna da 1ª linha comoString, ounullse não houver linhas.SqliteDb.lastInsertRowid()— rowid do último INSERT (long).SqliteDb.changes()— linhas alteradas pela última instrução.
Exemplo completo (copiar, colar e rodar)
package com.exemplo;
import dev.crossfly.ui.*; // Window
import dev.crossfly.ui.layout.*; // VerticalLayout
import dev.crossfly.sqlite.*; // SqliteDb, SqliteCursor
/** Tela principal executável. Aponte o launcher (classname) e rode: 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 person(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
// CREATE — parâmetros posicionais (? nº 1 = name, ? nº 2 = age)
int inserted = db.execute("INSERT INTO person(name, age) VALUES(?, ?)", "Alice", 30);
long id = db.lastInsertRowid(); // rowid gerado
System.out.println(inserted + " linha(s), id=" + id);
// READ — cursor: colunas 0-based
try (SqliteCursor c = db.query("SELECT name, age FROM person WHERE age > ?", 18))
{
while (c.next())
System.out.println(c.getString(0) + " = " + c.getInt(1)); // col 0 = name, col 1 = age
}
// READ escalar — atalhos
long total = db.queryLong("SELECT count(*) FROM person", 0);
String nome = db.queryString("SELECT name FROM person WHERE id = ?", id);
// UPDATE — retorna nº de linhas afetadas
int updated = db.execute("UPDATE person SET age = ? WHERE id = ?", 31, id);
// DELETE
int deleted = db.execute("DELETE FROM person WHERE id = ?", id);
}
}
}
O trecho abaixo mostra só o miolo. Para rodar, coloque-o no esqueleto
MainWindowacima.
Trecho mínimo
// verificado na fonte: execute (bind 1-based), query + cursor (getters 0-based), queryLong/queryString
import dev.crossfly.sqlite.*;
try (SqliteDb db = SqliteDb.open("app.db"))
{
db.exec("CREATE TABLE IF NOT EXISTS person(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
// CREATE — parâmetros posicionais (? nº 1 = name, ? nº 2 = age)
int inserted = db.execute("INSERT INTO person(name, age) VALUES(?, ?)", "Alice", 30);
long id = db.lastInsertRowid(); // rowid gerado
System.out.println(inserted + " linha(s), id=" + id);
// READ — cursor: colunas 0-based
try (SqliteCursor c = db.query("SELECT name, age FROM person WHERE age > ?", 18))
{
while (c.next())
System.out.println(c.getString(0) + " = " + c.getInt(1)); // col 0 = name, col 1 = age
}
// READ escalar — atalhos
long total = db.queryLong("SELECT count(*) FROM person", 0);
String nome = db.queryString("SELECT name FROM person WHERE id = ?", id);
// UPDATE — retorna nº de linhas afetadas
int updated = db.execute("UPDATE person SET age = ? WHERE id = ?", 31, id);
// DELETE
int deleted = db.execute("DELETE FROM person WHERE id = ?", id);
}
Aprofunde-se
- Guia de storage SQLite · Guia de desenvolvimento
- Receitas irmãs: Abrir/criar banco · Transação e escrita em massa · Uso fora da paint thread
Esta página foi útil?Obrigado pelo feedback!