La libreria androidx.sqlite
contiene interfacce astratte insieme a implementazioni di base che possono essere utilizzate per creare librerie personalizzate che accedono a SQLite. Ti consigliamo di utilizzare la libreria Room, che fornisce
un livello di astrazione su SQLite per consentire un accesso più solido al database sfruttando
tutta la potenza di SQLite.
Configurare le dipendenze
Per configurare SQLite nel tuo progetto KMP, aggiungi le dipendenze per gli artefatti nel
file build.gradle.kts
per il tuo modulo:
[versions]
sqlite = "2.5.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" }
API del driver SQLite
Le librerie androidx.sqlite
offrono API di basso livello per comunicare con
la libreria SQLite inclusa nella libreria quando si utilizza
androidx.sqlite:sqlite-bundled
o nella piattaforma host, come Android o iOS
quando si utilizza androidx.sqlite:sqlite-framework
. Le API seguono da vicino la funzionalità principale dell'API SQLite C.
Esistono tre interfacce principali:
SQLiteDriver
: è il punto di accesso per utilizzare SQLite ed è responsabile dell'apertura delle connessioni al database.SQLiteConnection
: è la rappresentazione dell'oggettosqlite3
.SQLiteStatement
: è la rappresentazione dell'oggettosqlite3_stmt
.
L'esempio seguente mostra le API principali:
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()
}
Come per le API C di SQLite, l'utilizzo comune prevede di:
- Apri una connessione al database utilizzando l'implementazione
SQLiteDriver
di cui è stata creata un'istanza. - Prepara un'istruzione SQL utilizzando
SQLiteConnection.prepare()
- Esegui un
SQLiteStatement
nel seguente modo:- Se vuoi, puoi associare gli argomenti utilizzando le funzioni
bind*()
. - Esegui l'iterazione sul set di risultati utilizzando la funzione
step()
. - Leggi le colonne dal set di risultati utilizzando le funzioni
get*()
.
- Se vuoi, puoi associare gli argomenti utilizzando le funzioni
Implementazioni dei conducenti
La seguente tabella riassume le implementazioni dei driver disponibili:
Nome del corso |
Elemento |
Piattaforme supportate |
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 (computer) |
L'implementazione consigliata da utilizzare è BundledSQLiteDriver
, disponibile in
androidx.sqlite:sqlite-bundled
. Include la libreria SQLite compilata dal codice sorgente, offrendo la versione più aggiornata e la coerenza su tutte le piattaforme KMP supportate.
Driver SQLite e Room
Le API del driver sono utili per le interazioni di basso livello con un database SQLite. Per una libreria ricca di funzionalità che fornisce un accesso più solido a SQLite, è consigliata Room.
Un RoomDatabase
si basa su un SQLiteDriver
per eseguire operazioni sul database e
deve essere configurata un'implementazione utilizzando
RoomDatabase.Builder.setDriver()
. Room fornisce
RoomDatabase.useReaderConnection
e
RoomDatabase.useWriterConnection
per un accesso più diretto alle connessioni al database gestite.
Esegui la migrazione a Kotlin Multiplatform
Qualsiasi utilizzo di chiamate SQLite di basso livello deve essere migrato alle controparti del driver SQLite.
Kotlin Multiplatform
Esegui una transazione utilizzando SQLiteConnection
di basso livello
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")
}
Esegui una query senza risultati
val connection: SQLiteConnection = ...
connection.execSQL("ALTER TABLE ...")
Esegui una query con un risultato, ma senza argomenti
val connection: SQLiteConnection = ...
connection.prepare("SELECT * FROM Pet").use { statement ->
while (statement.step()) {
// read columns
statement.getInt(0)
statement.getText(1)
}
}
Esegui una query con risultato e argomenti
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 Android
Eseguire una transazione utilizzando SupportSQLiteDatabase
val database: SupportSQLiteDatabase = ...
database.beginTransaction()
try {
// perform database operations in transaction
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
Esegui una query senza risultati
val database: SupportSQLiteDatabase = ...
database.execSQL("ALTER TABLE ...")
Esegui una query con un risultato, ma senza argomenti
val database: SupportSQLiteDatabase = ...
database.query("SELECT * FROM Pet").use { cursor ->
while (cusor.moveToNext()) {
// read columns
cursor.getInt(0)
cursor.getString(1)
}
}
Esegui una query con risultato e argomenti
database.query("SELECT * FROM Pet WHERE id = ?", id).use { cursor ->
if (cursor.moveToNext()) {
// row found, read columns
} else {
// row not found
}
}