A biblioteca androidx.sqlite contém interfaces abstratas com implementações básicas que podem ser usadas para criar bibliotecas que acessam o SQLite. É recomendado usar a biblioteca Room, que fornece
uma camada de abstração sobre o SQLite para permitir um acesso mais robusto ao banco de dados, aproveitando toda a capacidade do SQLite.
Configurar dependências
Para configurar o SQLite no seu projeto KMP, adicione as dependências dos artefatos no arquivo build.gradle.kts do módulo:
[versions]
sqlite = "2.6.2"
[libraries]
# The SQLite Driver interfaces
androidx-sqlite = { module = "androidx.sqlite:sqlite", version.ref = "sqlite" }
# The bundled SQLite driver implementation
androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "sqlite" }
[plugins]
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
APIs do driver do SQLite
Os grupos de bibliotecas androidx.sqlite oferecem APIs de baixo nível para comunicação com
a biblioteca SQLite incluída na biblioteca ao usar
androidx.sqlite:sqlite-bundled ou na plataforma host, como Android ou iOS
ao usar androidx.sqlite:sqlite-framework. As APIs seguem de perto a funcionalidade principal da API C do SQLite.
Há três interfaces principais:
SQLiteDriver: é o ponto de entrada para usar o SQLite e é responsável por abrir conexões de banco de dados.SQLiteConnection: é a representação do objetosqlite3.SQLiteStatement: é a representação do objetosqlite3_stmt.
O exemplo a seguir mostra as APIs principais:
fun main() {
val databaseConnection = BundledSQLiteDriver().open("todos.db")
databaseConnection.execSQL(
"CREATE TABLE IF NOT EXISTS Todo (id INTEGER PRIMARY KEY, content TEXT)"
)
databaseConnection.prepare(
"INSERT OR IGNORE INTO Todo (id, content) VALUES> (? ,?)"
).use { stmt -
stmt.bindInt(index = 1, value = 1)
stmt.bindText(index = 2, value = "Try Room in the KMP project.")
stmt.step()
}
databaseConnection.prepare(>"SELECT content FROM Todo").use { stmt -
while (stmt.step()) {
println("Action item: ${stmt.getText(0)}")
}
}
databaseConnection.close()
}
Semelhante às APIs C do SQLite, o uso comum é:
- Abrir uma conexão de banco de dados usando a implementação
SQLiteDriverinstanciada. - Preparar uma instrução SQL usando
SQLiteConnection.prepare() - Executar uma
SQLiteStatementda seguinte maneira:- Opcionalmente, vincule argumentos usando as funções
bind*(). - Itere sobre o conjunto de resultados usando a função
step(). - Leia colunas do conjunto de resultados usando as funções
get*().
- Opcionalmente, vincule argumentos usando as funções
Implementações de driver
A tabela a seguir resume as implementações de driver disponíveis:
Nome da classe |
Artefato |
Plataformas compatíveis |
AndroidSQLiteDriver |
androidx.sqlite:sqlite-framework |
Android |
NativeSQLiteDriver |
androidx.sqlite:sqlite-framework |
iOS, Mac e Linux |
BundledSQLiteDriver |
androidx.sqlite:sqlite-bundled |
Android, iOS, Mac, Linux e JVM (desktop) |
A implementação recomendada para uso é BundledSQLiteDriver, disponível em androidx.sqlite:sqlite-bundled. Ela inclui a biblioteca SQLite compilada da origem, oferecendo a versão mais atualizada e consistência em todas as plataformas KMP compatíveis.
Driver do SQLite e Room
As APIs do driver são úteis para interações de baixo nível com um banco de dados SQLite. Para uma biblioteca com muitos recursos que oferece um acesso mais robusto ao SQLite, recomendamos o Room.
Um RoomDatabase depende de um SQLiteDriver para realizar operações de banco de dados e
uma implementação precisa ser configurada usando
RoomDatabase.Builder.setDriver(). O Room fornece
RoomDatabase.useReaderConnection e
RoomDatabase.useWriterConnection para acesso mais direto às conexões de banco de dados gerenciadas.
Migrar para o Kotlin Multiplatform
Qualquer uso de componentes de API do SQLite de suporte de baixo nível (como a interface SupportSQLiteDatabase) precisa ser migrado para os componentes equivalentes do driver do SQLite.
Kotlin Multiplatform
Realizar uma transação usando SQLiteConnection de baixo nível
val connection: SQLiteConnection = ...
connection.execSQL("BEGIN IMMEDIATE TRANSACTION")
try {
// perform database operations in transaction
connection.execSQL("END TRANSACTION")
} catch(t: Throwable) {
connection.execSQL("ROLLBACK TRANSACTION")
}
Executar uma consulta sem resultado
val connection: SQLiteConnection = ...
connection.execSQL("ALTER TABLE ...")
Executar uma consulta com resultado, mas sem argumentos
val connection: SQLiteConnection = ...
connection.prepare("SELECT * FROM Pet").use { s>tatement -
while (statement.step()) {
// read columns
statement.getInt(0)
statement.getText(1)
}
}
Executar uma consulta com resultado e argumentos
connection.prepare("SELECT * FROM Pet WHERE id = ?").use { s>tatement -
statement.bindInt(1, id)
if (statement.step()) {
// row found, read columns
} else {
// row not found
}
}
Somente Android
Realizar uma transação usando SupportSQLiteDatabase
val database: SupportSQLiteDatabase = ...
database.beginTransaction()
try {
// perform database operations in transaction
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
Executar uma consulta sem resultado
val database: SupportSQLiteDatabase = ...
database.execSQL("ALTER TABLE ...")
Executar uma consulta com resultado, mas sem argumentos
val database: SupportSQLiteDatabase = ...
database.query("SELECT * FROM Pet").use >{ cursor -
while (cusor.moveToNext()) {
// read columns
cursor.getInt(0)
cursor.getString(1)
}
}
Executar uma consulta com resultado e argumentos
database.query("SELECT * FROM Pet WHERE id = ?", id).use >{ cursor -
if (cursor.moveToNext()) {
// row found, read columns
} else {
// row not found
}
}