# Como abrir ou criar um banco SQLite

> Abrir/criar um arquivo .db com try-with-resources, usar banco em memória e criar tabelas.

Source: https://crossfly.dev/pt/docs/cookbook/data/abrir-banco — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Como abrir ou criar um banco SQLite

**Propósito.** Abrir (ou criar, se não existir) um banco SQLite e criar suas tabelas. No CrossFly a porta de entrada é `SqliteDb`, um handle `AutoCloseable` — sempre use `try (...)` para garantir o fechamento da conexão nativa.

## APIs usadas
- `SqliteDb.open(String filename)` — abre/cria um banco **não criptografado** em read/write (`OPEN_DEFAULT = OPEN_READWRITE | OPEN_CREATE`). Retorna um `SqliteDb`.
- `SqliteDb.openMemory()` — abre um banco **em memória** (`:memory:`), volátil: some ao fechar. Ideal para testes e caches temporários.
- `SqliteDb.exec(String sql)` — roda uma ou mais instruções **sem resultado** (DDL, PRAGMA, DML em lote). Use para `CREATE TABLE`, `CREATE INDEX`, `PRAGMA ...`. Lança `SqliteException` em erro.
- `SqliteDb.close()` — fecha a conexão nativa. **Idempotente** (chamar duas vezes é seguro). O `try-with-resources` chama isso automaticamente.
- `SqliteDb.version()` — retorna a string de versão da biblioteca SQLite (útil para diagnóstico).

> **Caminho do arquivo.** Passe um caminho de arquivo gravável (por plataforma). Não use `Gdx.graphics` para nada aqui; o SQLite é independente da UI. Para o local de arquivos por plataforma, veja o guia de storage.

## Exemplo completo (copiar, colar e rodar)

```java
package com.exemplo;

import dev.crossfly.ui.*;                     // Window
import dev.crossfly.ui.layout.*;             // VerticalLayout
import dev.crossfly.sqlite.*;                // SqliteDb, SqliteException

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

      // 1) Banco em arquivo (criado se não existir)
      try (SqliteDb db = SqliteDb.open("app.db"))
      {
         db.exec(
            "CREATE TABLE IF NOT EXISTS person(" +
            "  id   INTEGER PRIMARY KEY," +
            "  name TEXT NOT NULL," +
            "  age  INTEGER)");
         // ... use o banco aqui ...
      }
      // conexão já fechada ao sair do try

      // 2) Banco em memória (volátil) — bom para testes
      try (SqliteDb mem = SqliteDb.openMemory())
      {
         mem.exec("CREATE TABLE t(id INTEGER PRIMARY KEY, v TEXT)");
         // ... vive apenas enquanto 'mem' estiver aberto ...
      }
   }
}
```

> O trecho abaixo mostra **só o miolo**. Para rodar, coloque-o no esqueleto `MainWindow` acima.

## Trecho mínimo
```java
// verificado na fonte: SqliteDb.open / openMemory / exec
import dev.crossfly.sqlite.*;

// 1) Banco em arquivo (criado se não existir)
try (SqliteDb db = SqliteDb.open("app.db"))
{
   db.exec(
      "CREATE TABLE IF NOT EXISTS person(" +
      "  id   INTEGER PRIMARY KEY," +
      "  name TEXT NOT NULL," +
      "  age  INTEGER)");
   // ... use o banco aqui ...
}
// conexão já fechada ao sair do try

// 2) Banco em memória (volátil) — bom para testes
try (SqliteDb mem = SqliteDb.openMemory())
{
   mem.exec("CREATE TABLE t(id INTEGER PRIMARY KEY, v TEXT)");
   // ... vive apenas enquanto 'mem' estiver aberto ...
}
```

## Aprofunde-se
- [Guia de storage SQLite](/docs/data-and-services/storage-sqlite) · Guia de desenvolvimento
- Receitas irmãs: [CRUD parametrizado](/docs/cookbook/data/crud) · [Banco criptografado](/docs/cookbook/data/banco-criptografado) · [Uso fora da paint thread](/docs/cookbook/data/banco-fora-da-paint-thread)
