ذخیره داده‌ها در پایگاه داده محلی بااستفاده از Room   بخشی از Android Jetpack.

با Kotlin چندپلاتفرمی امتحان کنید
Kotlin Multiplatform امکان هم‌رسانی لایه پایگاه داده با پلاتفرم‌های دیگر را فراهم می‌کند. آشنایی با نحوه راه‌اندازی و کار با Room Database در KMP

برنامه‌هایی که با مقادیر غیرجزئی داده‌های ساختاریافته سروکار دارند می‌توانند از ذخیره محلی آن داده‌ها بهره زیادی ببرند. رایج‌ترین مورد استفاده، ذخیره کردن بخش‌های مربوطه داده‌ها در حافظه نهان است تا وقتی دستگاه نمی‌تواند به شبکه دسترسی داشته باشد، کاربران شما همچنان بتوانند آن محتوا را در حالت آفلاین مرور کنند.

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

  • درستی‌سنجی زمان ترجمه پرسمان‌های SQL.
  • گزارمان‌های راحتی که کد کلیشه‌ای تکراری و مستعد خطا را به‌حداقل می‌رسانند.
  • مسیرهای انتقال پایگاه داده ساده‌شده.

توصیه می‌کنیم به‌جای استفاده مستقیم از میاناهای برنامه‌سازی کاربردی SQLite، از Room استفاده کنید.

راه‌اندازی

برای استفاده از Room در برنامه‌تان، وابستگی‌های زیر را به فایل build.gradle.kts واحدتان اضافه کنید. Room 3.0 برای پردازش گزارمان به KSP نیاز دارد.

کاتلین

dependencies {
    val room_version = "3.0.3"

    implementation("androidx.room3:room3-runtime:$room_version")
    ksp("androidx.room3:room3-compiler:$room_version")
}

گرووی

dependencies {
    def room_version = "3.0.3"

    implementation "androidx.room3:room3-runtime:$room_version"

    ksp "androidx.room3:room3-compiler:$room_version"
}

اجزای اصلی

سه مؤلفه اصلی در «اتاق» وجود دارد:

  • کلاس پایگاه داده که پایگاه داده را نگه می‌دارد و به‌عنوان نقطه دسترسی اصلی برای اتصال اساسی به داده‌های پایدار برنامه شما عمل می‌کند.
  • موجودیت‌های داده که جدول‌ها را در پایگاه داده برنامه‌تان نشان می‌دهند.
  • اشیاء دسترسی داده (DAOs) که توابعی را ارائه می‌دهند که برنامه‌تان می‌تواند از آن‌ها برای جستجو، به‌روزرسانی، درج، و حذف داده‌ها در پایگاه داده استفاده کند.

کلاس پایگاه داده نمونه‌هایی از «اشیا دسترسی به داده» مرتبط با آن پایگاه داده را دراختیار برنامه شما قرار می‌دهد. به‌نوبه خود، برنامه می‌تواند از DAOها برای بازیابی داده‌ها از پایگاه داده به‌عنوان نمونه‌هایی از اشیای موجودیت داده مرتبط استفاده کند. برنامه همچنین می‌تواند از موجودیت‌های داده تعریف‌شده برای به‌روزرسانی ردیف‌ها از جدول‌های مربوطه یا برای ایجاد ردیف‌های جدید برای درج استفاده کند. شکل ۱ رابطه بین مؤلفه‌های مختلف Room را نشان می‌دهد.

شکل ۱. نمودار معماری کتابخانه Room.

پیاده‌سازی نمونه

این بخش نمونه‌ای از پیاده‌سازی پایگاه داده Room با یک نهاد داده و یک DAO را ارائه می‌دهد.

موجودیت داده

کد زیر موجودیت داده User را تعریف می‌کند. هر نمونه از User نشان‌دهنده یک ردیف در جدول user در پایگاه داده برنامه است.

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String,
    @ColumnInfo(name = "last_name") val lastName: String
)

برای کسب اطلاعات بیشتر درباره موجودیت‌های داده در Room، به تعریف داده بااستفاده از موجودیت‌های Room مراجعه کنید.

شیء دسترسی داده (DAO)

کد زیر یک DAO به‌نام UserDao را تعریف می‌کند. UserDao عملکردهایی را که بقیه برنامه برای تعامل با داده‌های جدول user استفاده می‌کنند ارائه می‌دهد.

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    suspend fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    suspend fun loadAllByIds(userIds: IntArray): List<User>

    @Query(
        """
        SELECT * FROM user
        WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1
        """
    )
    suspend fun findByName(first: String, last: String): User

    @Insert
    suspend fun insertAll(vararg users: User)

    @Delete
    suspend fun delete(user: User)
}

برای کسب اطلاعات بیشتر درباره DAO، به دسترسی به داده‌ها بااستفاده از Room DAO مراجعه کنید.

پایگاه داده

کد زیر کلاس AppDatabase را برای نگهداری پایگاه داده تعریف می‌کند. AppDatabase پیکربندی پایگاه داده را تعریف می‌کند و به‌عنوان نقطه دسترسی اصلی برنامه به داده‌های پایدار عمل می‌کند. کلاس پایگاه داده باید شرایط زیر را داشته باشد:

  • کلاس باید با حاشیه‌نویسی @Database حاشیه‌نویسی شود که شامل آرایه entities است که همه موجودیت‌های داده مرتبط با پایگاه داده را فهرست می‌کند.
  • کلاس باید یک کلاس انتزاعی باشد که RoomDatabase را گسترش می‌دهد.
  • برای هر کلاس DAO مرتبط با پایگاه داده، کلاس پایگاه داده باید تابع انتزاعی‌ای تعریف کند که هیچ آرگومانی نگیرد و نمونه‌ای از کلاس DAO را برگرداند.

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

توجه: اگر برنامه‌تان در یک فرایند اجرا می‌شود، باید هنگام نمونه‌سازی شیء AppDatabase از الگوی طراحی تک‌نمونه پیروی کنید. هر نمونه RoomDatabase نسبتاً گران است و شما به‌ندرت به دسترسی به چند نمونه در یک فرایند نیاز دارید.

اگر برنامه‌تان در چندین فرایند اجرا می‌شود، enableMultiInstanceInvalidation() را در فراخوانی سازنده پایگاه داده‌تان بگنجانید. به این ترتیب، وقتی نمونه‌ای از AppDatabase در هر فرایند دارید، می‌توانید فایل پایگاه داده هم‌رسانی‌شده را در یک فرایند باطل کنید، و این باطل‌سازی به‌طور خودکار به نمونه‌های AppDatabase در فرایندهای دیگر منتشر می‌شود.

کاربرد

پس‌از تعریف نهاد داده، DAO، و شیء پایگاه داده، می‌توانید از کد زیر برای ایجاد نمونه‌ای از پایگاه داده استفاده کنید:

val db =
    Room.databaseBuilder<AppDatabase>(applicationContext, "database-name")
        .setDriver(AndroidSQLiteDriver())
        .build()

سپس می‌توانید از توابع انتزاعی AppDatabase برای دریافت نمونه‌ای از DAO استفاده کنید. به‌نوبه خود، می‌توانید از توابع نمونه DAO برای تعامل با پایگاه داده استفاده کنید:

val userDao = db.userDao()
val users: List<User> = userDao.getAll()

منابع بیشتر

برای کسب اطلاعات بیشتر درباره «اتاق»، منابع تکمیلی زیر را ببینید:

نمونه‌ها