SQLite (Kotlin หลายแพลตฟอร์ม)

ไลบรารี androidx.sqlite มีอินเทอร์เฟซแบบนามธรรมพร้อมกับการใช้งานพื้นฐาน ซึ่งสามารถใช้เพื่อสร้างไลบรารีของคุณเองที่เข้าถึง SQLite ได้ คุณอาจต้องพิจารณาใช้ไลบรารี Room ซึ่งมี เลเยอร์การแยกข้อมูลเหนือ SQLite เพื่อให้เข้าถึงฐานข้อมูลได้อย่างมีประสิทธิภาพมากขึ้น พร้อมทั้งใช้ประโยชน์จากความสามารถทั้งหมดของ SQLite

ตั้งค่าทรัพยากร Dependency

หากต้องการตั้งค่า 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" }

SQLite Driver APIs

กลุ่มไลบรารี 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()
}

การใช้งานทั่วไปจะคล้ายกับ SQLite C API ดังนี้

  • เปิดการเชื่อมต่อฐานข้อมูลโดยใช้SQLiteDriver การใช้งานที่สร้างอินสแตนซ์
  • เตรียมคำสั่ง SQL โดยใช้ SQLiteConnection.prepare()
  • เรียกใช้ SQLiteStatement โดยทำดังนี้
    1. คุณจะเชื่อมโยงอาร์กิวเมนต์โดยใช้ฟังก์ชัน bind*() หรือไม่ก็ได้
    2. วนซ้ำชุดผลลัพธ์โดยใช้ฟังก์ชัน step()
    3. อ่านคอลัมน์จากชุดผลลัพธ์โดยใช้ฟังก์ชัน get*()

การใช้งานไดรเวอร์

ตารางต่อไปนี้สรุปการใช้งานไดรเวอร์ที่มี

ชื่อชั้นเรียน

อาร์ติแฟกต์

แพลตฟอร์มที่รองรับ

AndroidSQLiteDriver androidx.sqlite:sqlite-framework

Android

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 และ Room

API ไดรเวอร์มีประโยชน์สำหรับการโต้ตอบระดับต่ำกับฐานข้อมูล SQLite หากต้องการคลังที่มีฟีเจอร์มากมายซึ่งให้การเข้าถึง SQLite ที่มีประสิทธิภาพมากขึ้น เราขอแนะนำให้ใช้ Room

RoomDatabase ต้องอาศัย SQLiteDriver เพื่อดำเนินการกับฐานข้อมูล และ ต้องมีการติดตั้งใช้งานที่กำหนดค่าโดยใช้ RoomDatabase.Builder.setDriver() Room มี RoomDatabase.useReaderConnection และ RoomDatabase.useWriterConnection เพื่อให้เข้าถึงการเชื่อมต่อฐานข้อมูลที่มีการจัดการได้โดยตรงมากขึ้น

ย้ายข้อมูลไปยัง Kotlin Multiplatform

การใช้การเรียก SQLite ระดับต่ำจะต้องย้ายข้อมูลไปยังการเรียก SQLite Driver ที่เทียบเท่า

Kotlin Multiplatform

ทำธุรกรรมโดยใช้ 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
  }
}