Библиотека androidx.sqlite
содержит абстрактные интерфейсы и базовые реализации, которые можно использовать для создания собственных библиотек, работающих с SQLite. Возможно, вам стоит рассмотреть библиотеку Room , которая предоставляет уровень абстракции над SQLite для более надёжного доступа к базе данных и использования всех возможностей SQLite.
Настройка зависимостей
Чтобы настроить SQLite в вашем проекте KMP, добавьте зависимости для артефактов в файле build.gradle.kts
для вашего модуля:
[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 драйверов SQLite
Группы библиотек androidx.sqlite
предлагают низкоуровневые API для взаимодействия с библиотекой SQLite, которые либо включены в библиотеку при использовании androidx.sqlite:sqlite-bundled
, либо находятся на хост-платформе, например, Android или iOS при использовании androidx.sqlite:sqlite-framework
. Эти API точно соответствуют основным функциональным возможностям SQLite C API.
Существует 3 основных интерфейса:
-
SQLiteDriver
— это точка входа для использования SQLite, которая отвечает за открытие подключений к базе данных. -
SQLiteConnection
— это представление объектаsqlite3
. -
SQLiteStatement
— это представление объектаsqlite3_stmt
.
В следующем примере показаны основные API:
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()
}
Подобно API SQLite C, обычно используется для:
- Откройте соединение с базой данных, используя реализованный экземпляр
SQLiteDriver
. - Подготовьте SQL-оператор с помощью
SQLiteConnection.prepare()
- Выполните
SQLiteStatement
следующим образом:- При необходимости можно связать аргументы с помощью функций
bind*()
. - Выполните итерацию по результирующему набору с помощью функции
step()
. - Прочитайте столбцы из набора результатов с помощью функций
get*()
.
- При необходимости можно связать аргументы с помощью функций
Реализации драйверов
В следующей таблице приведены доступные реализации драйверов:
Имя класса | Артефакт | Поддерживаемые платформы |
AndroidSQLiteDriver | androidx.sqlite:sqlite-framework | Андроид |
NativeSQLiteDriver | androidx.sqlite:sqlite-framework | iOS, Mac и Linux |
BundledSQLiteDriver | androidx.sqlite:sqlite-bundled | Android, iOS, Mac, Linux и JVM (для ПК) |
Рекомендуемая реализация — BundledSQLiteDriver
, доступный в androidx.sqlite:sqlite-bundled
. Он включает в себя библиотеку SQLite, скомпилированную из исходного кода, обеспечивая самую актуальную версию и согласованность на всех поддерживаемых платформах KMP.
Драйвер и комната SQLite
API драйвера полезны для низкоуровневого взаимодействия с базой данных SQLite. Для многофункциональной библиотеки, обеспечивающей более надёжный доступ к SQLite, рекомендуется использовать Room.
RoomDatabase
использует SQLiteDriver
для выполнения операций с базой данных, и для настройки реализации требуется использовать RoomDatabase.Builder.setDriver()
. Room предоставляет RoomDatabase.useReaderConnection
и RoomDatabase.useWriterConnection
для более прямого доступа к управляемым подключениям к базе данных.
Переход на Kotlin Multiplatform
Любое использование низкоуровневых вызовов SQLite необходимо перенести в их аналоги драйвера SQLite.
Kotlin Мультиплатформенный
Выполнение транзакции с использованием низкоуровневого SQLiteConnection
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")
}
Выполнить запрос без результата
val connection: SQLiteConnection = ...
connection.execSQL("ALTER TABLE ...")
Выполнить запрос с результатом, но без аргументов
val connection: SQLiteConnection = ...
connection.prepare("SELECT * FROM Pet").use { statement ->
while (statement.step()) {
// read columns
statement.getInt(0)
statement.getText(1)
}
}
Выполнить запрос с результатом и аргументами
connection.prepare("SELECT * FROM Pet WHERE id = ?").use { statement ->
statement.bindInt(1, id)
if (statement.step()) {
// row found, read columns
} else {
// row not found
}
}
только для Android
Выполнение транзакции с использованием SupportSQLiteDatabase
val database: SupportSQLiteDatabase = ...
database.beginTransaction()
try {
// perform database operations in transaction
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
Выполнить запрос без результата
val database: SupportSQLiteDatabase = ...
database.execSQL("ALTER TABLE ...")
Выполнить запрос с результатом, но без аргументов
val database: SupportSQLiteDatabase = ...
database.query("SELECT * FROM Pet").use { cursor ->
while (cusor.moveToNext()) {
// read columns
cursor.getInt(0)
cursor.getString(1)
}
}
Выполнить запрос с результатом и аргументами
database.query("SELECT * FROM Pet WHERE id = ?", id).use { cursor ->
if (cursor.moveToNext()) {
// row found, read columns
} else {
// row not found
}
}