SQLite را برای KMP تنظیم کنید

کتابخانه androidx.sqlite شامل رابط‌های انتزاعی به همراه پیاده‌سازی‌های اولیه است که می‌توانند برای ساخت کتابخانه‌های شخصی شما که به SQLite دسترسی دارند، استفاده شوند. شاید بخواهید از کتابخانه Room استفاده کنید که یک لایه انتزاعی روی SQLite فراهم می‌کند تا دسترسی به پایگاه داده قوی‌تری را فراهم کند و در عین حال از تمام قدرت SQLite بهره ببرد.

وابستگی‌ها را تنظیم کنید

برای تنظیم SQLite در پروژه KMP خود، وابستگی‌های مربوط به مصنوعات را در فایل build.gradle.kts مربوط به ماژول خود اضافه کنید:

[versions]
sqlite = "2.7.0"

[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" }

رابط‌های برنامه‌نویسی درایور SQLite

گروه‌های کتابخانه androidx.sqlite APIهای سطح پایینی را برای ارتباط با کتابخانه SQLite ارائه می‌دهند، چه در کتابخانه هنگام استفاده از androidx.sqlite:sqlite-bundled و چه در پلتفرم میزبان، مانند اندروید یا iOS هنگام استفاده از androidx.sqlite:sqlite-framework . این APIها عملکرد اصلی SQLite C API را به دقت دنبال می‌کنند.

سه رابط اصلی وجود دارد:

  • 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، الگوی استفاده رایج شامل این مراحل است:

  1. با استفاده از پیاده‌سازی نمونه‌سازی‌شده‌ی SQLiteDriver یک اتصال به پایگاه داده باز کنید.
  2. با استفاده از SQLiteConnection.prepare یک دستور SQL آماده کنید.
  3. با انجام موارد زیر، یک SQLiteStatement را اجرا کنید:
    1. اختیاری: آرگومان‌ها را با استفاده از توابع bind* مقید کنید.
    2. با استفاده از تابع step ، روی مجموعه نتایج تکرار کنید.
    3. با استفاده از توابع get* ستون‌هایی از مجموعه نتایج را بخوانید.

پیاده‌سازی درایور

جدول زیر خلاصه‌ای از پیاده‌سازی‌های درایور موجود را نشان می‌دهد:

نام کلاس

مصنوع

پلتفرم‌های پشتیبانی‌شده

AndroidSQLiteDriver androidx.sqlite:sqlite-framework

اندروید

NativeSQLiteDriver androidx.sqlite:sqlite-framework

آی‌او‌اس، مک و لینوکس

BundledSQLiteDriver androidx.sqlite:sqlite-bundled

اندروید، iOS، مک، لینوکس و JVM (دسکتاپ)

WebWorkerSQLiteDriver androidx.sqlite:sqlite-web

جاوا اسکریپت و وب اسمبلی (WasmJS)

پیاده‌سازی پیشنهادی برای استفاده، BundledSQLiteDriver است که در androidx.sqlite:sqlite-bundled موجود است. این شامل کتابخانه SQLite کامپایل شده از منبع است و به‌روزترین نسخه و سازگاری را در تمام پلتفرم‌های KMP پشتیبانی‌شده ارائه می‌دهد.

درایور و اتاق SQLite

رابط‌های برنامه‌نویسی کاربردی (API) درایور برای تعاملات سطح پایین با پایگاه داده SQLite مفید هستند. برای یک کتابخانه غنی از ویژگی‌ها که دسترسی قوی‌تری به SQLite فراهم می‌کند، Room را توصیه می‌کنیم.

یک RoomDatabase برای انجام عملیات پایگاه داده به SQLiteDriver متکی است و شما باید با استفاده از RoomDatabase.Builder.setDriver یک پیاده‌سازی را پیکربندی کنید. Room برای دسترسی مستقیم‌تر به اتصالات پایگاه داده مدیریت‌شده RoomDatabase.useReaderConnection و RoomDatabase.useWriterConnection را ارائه می‌دهد.

مهاجرت به کاتلین چند پلتفرمی

شما باید هرگونه استفاده از اجزای API سطح پایین Support SQLite، مانند رابط SupportSQLiteDatabase ، را به اجزای معادل SQLite Driver منتقل کنید.

کاتلین چندسکویی

انجام تراکنش با استفاده از 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
  }
}

فقط اندروید

انجام تراکنش با استفاده از 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 (cursor.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
  }
}