La biblioteca androidx.sqlite contiene interfaces abstractas junto con implementaciones básicas que se pueden usar para compilar tus propias bibliotecas que acceden a SQLite. Te recomendamos que uses la biblioteca de Room, que brinda una capa de abstracción para SQLite que permite acceder a la base de datos sin problemas y, al mismo tiempo, aprovecha toda la potencia de SQLite.
Configura dependencias
Para configurar SQLite en tu proyecto de KMP, agrega las dependencias de los artefactos en el archivo build.gradle.kts de tu módulo:
[versions]
sqlite = "2.7.1"
[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 de controladores de SQLite
Los grupos de bibliotecas androidx.sqlite ofrecen APIs de bajo nivel para comunicarse con la biblioteca de SQLite, ya sea incluida en la biblioteca cuando se usa androidx.sqlite:sqlite-bundled o en la plataforma host, como Android o iOS, cuando se usa androidx.sqlite:sqlite-framework. Las APIs siguen de cerca la funcionalidad principal de la API de SQLite en C.
Existen tres interfaces principales:
SQLiteDriver: Es el punto de entrada a SQLite, que se usa para abrir conexiones de base de datos.SQLiteConnection: Representa el objetosqlite3.SQLiteStatement: Representa el objetosqlite3_stmt.
En el siguiente ejemplo, se muestran las APIs principales:
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() }
Al igual que con las APIs en C de SQLite, el patrón de uso común consta de los siguientes pasos:
- Abrir una conexión de base de datos con la implementación de
SQLiteDriverque se creó - Prepara una sentencia de SQL con
SQLiteConnection.prepare. - Ejecuta un
SQLiteStatementde la siguiente manera:- Opcional: Vincula argumentos con las funciones
bind*. - Iterar el conjunto de resultados con la función
step - Leer columnas del conjunto de resultados con las funciones
get*
- Opcional: Vincula argumentos con las funciones
Implementaciones de controladores
En la siguiente tabla, se resumen las implementaciones de controladores disponibles:
Nombre de clase |
Artefacto |
Plataformas compatibles |
AndroidSQLiteDriver |
androidx.sqlite:sqlite-framework |
Android |
NativeSQLiteDriver |
androidx.sqlite:sqlite-framework |
iOS, Mac y Linux |
BundledSQLiteDriver |
androidx.sqlite:sqlite-bundled |
Android, iOS, Mac, Linux y JVM (computadoras) |
WebWorkerSQLiteDriver |
androidx.sqlite:sqlite-web |
JavaScript y WebAssembly (WasmJS) |
La implementación recomendada para usar es BundledSQLiteDriver, disponible en
androidx.sqlite:sqlite-bundled. Incluye la biblioteca de SQLite compilada desde la fuente, lo que ofrece la versión más actualizada y coherencia en todas las plataformas de KMP compatibles.
Controlador de SQLite y Room
Las APIs de controladores son útiles para las interacciones de bajo nivel con una base de datos SQLite. Para obtener una biblioteca con muchas funciones que proporcione un acceso más sólido a SQLite, te recomendamos Room.
Una RoomDatabase depende de un SQLiteDriver para realizar operaciones de bases de datos,
y debes configurar una implementación con
RoomDatabase.Builder.setDriver. Room proporciona RoomDatabase.useReaderConnection y RoomDatabase.useWriterConnection para un acceso más directo a las conexiones de bases de datos administradas.
Cómo migrar a Kotlin Multiplatform
Debes migrar cualquier uso de componentes de la API de SQLite de compatibilidad de bajo nivel,
como la interfaz SupportSQLiteDatabase, a los componentes equivalentes del controlador de
SQLite.
Kotlin multiplataforma
Realiza una transacción con SQLiteConnection de bajo nivel
val connection: SQLiteConnection = BundledSQLiteDriver().open("todos.db") connection.execSQL("BEGIN IMMEDIATE TRANSACTION") try { // perform database operations in transaction. connection.execSQL("END TRANSACTION") } catch (t: Throwable) { connection.execSQL("ROLLBACK TRANSACTION") }
Ejecuta una consulta sin resultados
val connection: SQLiteConnection = BundledSQLiteDriver().open("todos.db") connection.execSQL("ALTER TABLE ...")
Ejecuta una consulta con un resultado, pero sin argumentos
val connection: SQLiteConnection = BundledSQLiteDriver().open("todos.db") connection.prepare("SELECT * FROM Pet").use { statement -> while (statement.step()) { // read columns. statement.getInt(0) statement.getText(1) } }
Ejecuta una consulta con resultados y argumentos
connection.prepare("SELECT * FROM Pet WHERE id = ?").use { statement -> statement.bindInt(1, id) if (statement.step()) { // row found, read columns. } else { // row not found. } }
Solo para Android
Realiza una transacción con SupportSQLiteDatabase
val database: SupportSQLiteDatabase = ...
database.beginTransaction()
try {
// perform database operations in transaction
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
Ejecuta una consulta sin resultados
val database: SupportSQLiteDatabase = ...
database.execSQL("ALTER TABLE ...")
Ejecuta una consulta con un resultado, pero sin argumentos
val database: SupportSQLiteDatabase = ...
database.query("SELECT * FROM Pet").use { cursor ->
while (cursor.moveToNext()) {
// read columns
cursor.getInt(0)
cursor.getString(1)
}
}
Ejecuta una consulta con resultados y argumentos
database.query("SELECT * FROM Pet WHERE id = ?", id).use { cursor ->
if (cursor.moveToNext()) {
// row found, read columns
} else {
// row not found
}
}