Room পার্সিস্টেন্স লাইব্রেরিটি SQLite-এর উপর একটি অ্যাবস্ট্রাকশন লেয়ার প্রদান করে, যা SQLite-এর সম্পূর্ণ শক্তিকে কাজে লাগানোর পাশাপাশি আরও শক্তিশালী ডাটাবেস অ্যাক্সেসের সুযোগ করে দেয়। এই পৃষ্ঠাটি Kotlin Multiplatform (KMP) প্রোজেক্টে Room ব্যবহারের উপর আলোকপাত করে। Room ব্যবহার সম্পর্কে আরও তথ্যের জন্য, “Save data in a local database using Room” অথবা আমাদের অফিসিয়াল স্যাম্পলগুলো দেখুন।
নির্ভরতা সেট আপ করুন
আপনার KMP প্রোজেক্টে Room সেটআপ করতে, আপনার KMP মডিউলের build.gradle.kts ফাইলে আর্টিফ্যাক্টগুলোর জন্য ডিপেন্ডেন্সি যোগ করুন।
libs.versions.toml ফাইলে নির্ভরতাগুলো সংজ্ঞায়িত করুন:
[versions]
room = "2.8.4"
sqlite = "2.6.2"
ksp = "<kotlinCompatibleKspVersion>"
[libraries]
androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "sqlite" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
# Optional SQLite Wrapper available in version 2.8.0 and higher
androidx-room-sqlite-wrapper = { module = "androidx.room:room-sqlite-wrapper", version.ref = "room" }
[plugins]
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
androidx-room = { id = "androidx.room", version.ref = "room" }
রুম স্কিমা এবং কেএসপি প্লাগইন কনফিগার করতে রুম গ্রেডল প্লাগইনটি যোগ করুন।
plugins {
alias(libs.plugins.ksp)
alias(libs.plugins.androidx.room)
}
Room রানটাইম ডিপেন্ডেন্সি এবং বান্ডেল করা SQLite লাইব্রেরিটি যোগ করুন:
commonMain.dependencies {
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.sqlite.bundled)
}
// Optional when using Room SQLite Wrapper
androidMain.dependencies {
implementation(libs.androidx.room.sqlite.wrapper)
}
রুট dependencies ব্লকে KSP ডিপেন্ডেন্সিগুলো যোগ করুন। মনে রাখবেন, আপনার অ্যাপ যে সমস্ত টার্গেট ব্যবহার করে, সেগুলোকে অবশ্যই যোগ করতে হবে। আরও তথ্যের জন্য, “KSP with Kotlin Multiplatform ” দেখুন।
dependencies {
add("kspAndroid", libs.androidx.room.compiler)
add("kspIosSimulatorArm64", libs.androidx.room.compiler)
add("kspIosX64", libs.androidx.room.compiler)
add("kspIosArm64", libs.androidx.room.compiler)
// Add any other platform target you use in your project, for example kspDesktop
}
Room স্কিমা ডিরেক্টরি নির্ধারণ করুন। অতিরিক্ত তথ্যের জন্য, Room Gradle Plugin ব্যবহার করে স্কিমার অবস্থান সেট করুন দেখুন।
room {
schemaDirectory("$projectDir/schemas")
}
ডাটাবেস ক্লাসগুলি সংজ্ঞায়িত করুন
আপনার শেয়ার্ড KMP মডিউলের কমন সোর্স সেটের মধ্যে DAO এবং এনটিটি সহ @Database অ্যানোটেশনযুক্ত একটি ডাটাবেস ক্লাস তৈরি করতে হবে। এই ক্লাসগুলোকে কমন সোর্সে রাখলে সেগুলো সমস্ত টার্গেট প্ল্যাটফর্মে শেয়ার করা যাবে।
// shared/src/commonMain/kotlin/Database.kt
@Database(entities = [TodoEntity::class], version = 1)
@ConstructedBy(AppDatabaseConstructor::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun getDao(): TodoDao
}
// The Room compiler generates the `actual` implementations.
@Suppress("KotlinNoActualForExpect")
expect object AppDatabaseConstructor : RoomDatabaseConstructor<AppDatabase> {
override fun initialize(): AppDatabase
}
যখন আপনি RoomDatabaseConstructor ইন্টারফেস ব্যবহার করে একটি expect অবজেক্ট ডিক্লেয়ার করেন, তখন Room কম্পাইলার এর actual ইমপ্লিমেন্টেশনগুলো তৈরি করে। Android Studio নিম্নলিখিত ওয়ার্নিংটি দেখাতে পারে, যা আপনি @Suppress("KotlinNoActualForExpect") ব্যবহার করে দমন করতে পারেন:
Expected object 'AppDatabaseConstructor' has no actual declaration in module`
এরপরে, হয় একটি নতুন DAO ইন্টারফেস সংজ্ঞায়িত করুন অথবা বিদ্যমান কোনো একটিকে commonMain এ সরিয়ে নিন:
// shared/src/commonMain/kotlin/TodoDao.kt
@Dao
interface TodoDao {
@Insert
suspend fun insert(item: TodoEntity)
@Query("SELECT count(*) FROM TodoEntity")
suspend fun count(): Int
@Query("SELECT * FROM TodoEntity")
fun getAllAsFlow(): Flow<List<TodoEntity>>
}
আপনার সত্তাগুলোকে commonMain এ সংজ্ঞায়িত করুন বা সরান:
// shared/src/commonMain/kotlin/TodoEntity.kt
@Entity
data class TodoEntity(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val title: String,
val content: String
)
প্ল্যাটফর্ম-নির্দিষ্ট ডেটাবেস বিল্ডার তৈরি করুন
প্রতিটি প্ল্যাটফর্মে Room ইনস্ট্যানশিয়েট করার জন্য আপনাকে একটি ডাটাবেস বিল্ডার সংজ্ঞায়িত করতে হবে। ফাইল সিস্টেম এপিআই-এর ভিন্নতার কারণে, এপিআই-এর শুধুমাত্র এই অংশটিই প্ল্যাটফর্ম-নির্দিষ্ট সোর্স সেটে থাকা আবশ্যক।
অ্যান্ড্রয়েড
অ্যান্ড্রয়েডে, ডেটাবেসের অবস্থান সাধারণত Context.getDatabasePath() API-এর মাধ্যমে পাওয়া যায়। ডেটাবেস ইনস্ট্যান্স তৈরি করতে, ডেটাবেস পাথের সাথে একটি Context নির্দিষ্ট করতে হয়।
// shared/src/androidMain/kotlin/Database.android.kt
fun getDatabaseBuilder(context: Context): RoomDatabase.Builder<AppDatabase> {
val appContext = context.applicationContext
val dbFile = appContext.getDatabasePath("my_room.db")
return Room.databaseBuilder<AppDatabase>(
context = appContext,
name = dbFile.absolutePath
)
}
আইওএস
iOS-এ ডাটাবেস ইনস্ট্যান্স তৈরি করতে, NSFileManager ব্যবহার করে একটি ডাটাবেস পাথ প্রদান করুন, যা সাধারণত NSDocumentDirectory তে অবস্থিত।
// shared/src/iosMain/kotlin/Database.ios.kt
fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
val dbFilePath = documentDirectory() + "/my_room.db"
return Room.databaseBuilder<AppDatabase>(
name = dbFilePath,
)
}
private fun documentDirectory(): String {
val documentDirectory = NSFileManager.defaultManager.URLForDirectory(
directory = NSDocumentDirectory,
inDomain = NSUserDomainMask,
appropriateForURL = null,
create = false,
error = null,
)
return requireNotNull(documentDirectory?.path)
}
জেভিএম (ডেস্কটপ)
ডাটাবেস ইনস্ট্যান্স তৈরি করতে, জাভা বা কোটলিন এপিআই ব্যবহার করে একটি ডাটাবেস পাথ প্রদান করুন।
// shared/src/jvmMain/kotlin/Database.desktop.kt
fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
val dbFile = File(System.getProperty("java.io.tmpdir"), "my_room.db")
return Room.databaseBuilder<AppDatabase>(
name = dbFile.absolutePath,
)
}
ডাটাবেস ইনস্ট্যানশিয়েট করুন
একবার আপনি প্ল্যাটফর্ম-নির্দিষ্ট কনস্ট্রাক্টরগুলোর একটি থেকে RoomDatabase.Builder পেয়ে গেলে, প্রকৃত ডেটাবেস ইনস্ট্যানসিয়েশনের পাশাপাশি সাধারণ কোডেই Room ডেটাবেসের বাকি অংশ কনফিগার করতে পারবেন।
// shared/src/commonMain/kotlin/Database.kt
fun getRoomDatabase(
builder: RoomDatabase.Builder<AppDatabase>
): AppDatabase {
return builder
.setDriver(BundledSQLiteDriver())
.setQueryCoroutineContext(Dispatchers.IO)
.build()
}
একটি SQLite ড্রাইভার নির্বাচন করুন
পূর্ববর্তী কোড স্নিপেটটি Room ডাটাবেস কোন SQLite ড্রাইভার ব্যবহার করবে তা নির্ধারণ করার জন্য setDriver বিল্ডার ফাংশনটিকে কল করে। এই ড্রাইভারগুলো টার্গেট প্ল্যাটফর্মের উপর ভিত্তি করে ভিন্ন হয়। পূর্ববর্তী কোড স্নিপেটগুলো BundledSQLiteDriver ব্যবহার করে। এটিই প্রস্তাবিত ড্রাইভার, যাতে সোর্স থেকে কম্পাইল করা SQLite অন্তর্ভুক্ত থাকে, যা সমস্ত প্ল্যাটফর্মে SQLite-এর সবচেয়ে সামঞ্জস্যপূর্ণ এবং হালনাগাদ সংস্করণ সরবরাহ করে।
আপনি যদি OS-প্রদত্ত SQLite ব্যবহার করতে চান, তাহলে প্ল্যাটফর্ম-নির্দিষ্ট সোর্স সেটগুলিতে setDriver API ব্যবহার করুন যা একটি প্ল্যাটফর্ম-নির্দিষ্ট ড্রাইভার নির্দিষ্ট করে। উপলব্ধ ড্রাইভার ইমপ্লিমেন্টেশনগুলির বিবরণের জন্য ড্রাইভার ইমপ্লিমেন্টেশনস দেখুন। আপনি নিম্নলিখিতগুলির যেকোনো একটি ব্যবহার করতে পারেন:
-
androidMainএAndroidSQLiteDriver -
iosMainএNativeSQLiteDriver
NativeSQLiteDriver ব্যবহার করার জন্য, আপনাকে -lsqlite3 লিঙ্কার অপশনটি প্রদান করতে হবে, যাতে iOS অ্যাপটি সিস্টেম SQLite-এর সাথে ডাইনামিকভাবে লিঙ্ক করতে পারে।
// shared/build.gradle.kts
kotlin {
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "TodoApp"
isStatic = true
// Required when using NativeSQLiteDriver
linkerOpts.add("-lsqlite3")
}
}
}
একটি কো-রুটিন কনটেক্সট সেট করুন (ঐচ্ছিক)
অ্যান্ড্রয়েডে একটি RoomDatabase অবজেক্টকে ডেটাবেস অপারেশন সম্পাদনের জন্য RoomDatabase.Builder.setQueryExecutor() ব্যবহার করে ঐচ্ছিকভাবে শেয়ার্ড অ্যাপ্লিকেশন এক্সিকিউটর দিয়ে কনফিগার করা যেতে পারে।
যেহেতু এক্সিকিউটরগুলো KMP-এর সাথে সামঞ্জস্যপূর্ণ নয়, তাই Room-এর setQueryExecutor() API-টি commonMain এ উপলব্ধ নয়। এর পরিবর্তে, RoomDatabase অবজেক্টটিকে অবশ্যই একটি CoroutineContext দিয়ে কনফিগার করতে হবে, যা RoomDatabase.Builder.setCoroutineContext() ব্যবহার করে সেট করা যায়। যদি কোনো কনটেক্সট সেট করা না থাকে, তাহলে RoomDatabase অবজেক্টটি ডিফল্টভাবে Dispatchers.IO ব্যবহার করবে।
ক্ষুদ্রকরণ এবং অস্পষ্টকরণ
প্রজেক্টটি মিনিফাইড বা অবফাসকেটেড হলে আপনাকে অবশ্যই নিম্নলিখিত ProGuard রুলটি অন্তর্ভুক্ত করতে হবে, যাতে Room ডাটাবেস ডেফিনিশনের জেনারেটেড ইমপ্লিমেন্টেশনটি খুঁজে পেতে পারে:
-keep class * extends androidx.room.RoomDatabase { <init>(); }
কোটলিন মাল্টিপ্ল্যাটফর্মে স্থানান্তরিত করুন
Room মূলত একটি অ্যান্ড্রয়েড লাইব্রেরি হিসেবে তৈরি করা হয়েছিল এবং পরবর্তীতে এপিআই সামঞ্জস্যতার উপর জোর দিয়ে এটিকে কেএমপি-তে স্থানান্তরিত করা হয়। Room-এর কেএমপি সংস্করণটি বিভিন্ন প্ল্যাটফর্মে এবং অ্যান্ড্রয়েড-নির্দিষ্ট সংস্করণ থেকে কিছুটা ভিন্ন। এই পার্থক্যগুলো নিচে তালিকাভুক্ত ও বর্ণনা করা হলো।
সাপোর্ট SQLite থেকে SQLite ড্রাইভারে মাইগ্রেট করুন
androidx.sqlite.db তে থাকা SupportSQLiteDatabase এবং অন্যান্য API-এর যেকোনো ব্যবহারকে SQLite Driver API দিয়ে রিফ্যাক্টর করতে হবে, কারণ androidx.sqlite.db এর API-গুলো শুধুমাত্র Android-এর জন্য (লক্ষ্য করুন, এটি KMP প্যাকেজ থেকে ভিন্ন একটি প্যাকেজ)।
পূর্ববর্তী সংস্করণের সাথে সামঞ্জস্যতা বজায় রাখার জন্য, এবং যতক্ষণ পর্যন্ত RoomDatabase একটি SupportSQLiteOpenHelper.Factory দিয়ে কনফিগার করা থাকে (উদাহরণস্বরূপ, কোনো SQLiteDriver সেট করা না থাকলে), ততক্ষণ Room 'কম্প্যাটিবিলিটি মোড'-এ কাজ করে, যেখানে Support SQLite এবং SQLite Driver উভয় API-ই প্রত্যাশিতভাবে কাজ করে। এটি পর্যায়ক্রমিক মাইগ্রেশনকে সম্ভব করে তোলে, ফলে আপনাকে একবারে আপনার Support SQLite-এর সমস্ত ব্যবহারকে SQLite Driver-এ রূপান্তর করতে হয় না।
রুম এসকিউলাইট র্যাপার ব্যবহার করুন (ঐচ্ছিক)
androidx.room:room-sqlite-wrapper আর্টিফ্যাক্টটি মাইগ্রেশনের সময় SQLiteDriver এবং SupportSQLiteDatabase মধ্যে সংযোগ স্থাপনের জন্য এপিআই (API) প্রদান করে।
SQLiteDriver দিয়ে কনফিগার করা একটি RoomDatabase থেকে SupportSQLiteDatabase পেতে, নতুন এক্সটেনশন ফাংশন RoomDatabase.getSupportWrapper() ব্যবহার করুন। এই কম্প্যাটিবিলিটি র্যাপারটি SQLiteDriver গ্রহণ করার সময় SupportSQLiteDatabase এর বিদ্যমান ব্যবহার (যা প্রায়শই RoomDatabase.openHelper.writableDatabase থেকে পাওয়া যায়) বজায় রাখতে সাহায্য করে, বিশেষ করে সেইসব কোডবেসের জন্য যেখানে SupportSQLite API-এর ব্যাপক ব্যবহার রয়েছে এবং যারা BundledSQLiteDriver ব্যবহার করতে চায়।
মাইগ্রেশন সাবক্লাস রূপান্তর করুন
মাইগ্রেশন সাবক্লাসগুলোকে SQLite ড্রাইভারের সমতুল্য সংস্করণে মাইগ্রেট করতে হবে:
কোটলিন মাল্টিপ্ল্যাটফর্ম
অভিবাসন উপশ্রেণী
object Migration_1_2 : Migration(1, 2) {
override fun migrate(connection: SQLiteConnection) {
// …
}
}
স্বয়ংক্রিয় মাইগ্রেশন স্পেসিফিকেশন সাবক্লাস
class AutoMigrationSpec_1_2 : AutoMigrationSpec {
override fun onPostMigrate(connection: SQLiteConnection) {
// …
}
}
শুধুমাত্র অ্যান্ড্রয়েডের জন্য
অভিবাসন উপশ্রেণী
object Migration_1_2 : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
// …
}
}
স্বয়ংক্রিয় মাইগ্রেশন স্পেসিফিকেশন সাবক্লাস
class AutoMigrationSpec_1_2 : AutoMigrationSpec {
override fun onPostMigrate(db: SupportSQLiteDatabase) {
// …
}
}
ডাটাবেস কলব্যাক রূপান্তর করুন
ডাটাবেস কলব্যাকগুলিকে SQLite ড্রাইভারের অনুরূপ অংশে স্থানান্তর করতে হবে:
কোটলিন মাল্টিপ্ল্যাটফর্ম
object MyRoomCallback : RoomDatabase.Callback() {
override fun onCreate(connection: SQLiteConnection) {
// …
}
override fun onDestructiveMigration(connection: SQLiteConnection) {
// …
}
override fun onOpen(connection: SQLiteConnection) {
// …
}
}
শুধুমাত্র অ্যান্ড্রয়েডের জন্য
object MyRoomCallback : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
// …
}
override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
// …
}
override fun onOpen(db: SupportSQLiteDatabase) {
// …
}
}
@RawQuery DAO ফাংশনগুলিকে রূপান্তর করুন
@RawQuery দিয়ে টীকাযুক্ত যে ফাংশনগুলি অ্যান্ড্রয়েড-বহির্ভূত প্ল্যাটফর্মের জন্য কম্পাইল করা হয়, সেগুলিতে SupportSQLiteQuery এর পরিবর্তে RoomRawQuery টাইপের একটি প্যারামিটার ঘোষণা করতে হবে।
কোটলিন মাল্টিপ্ল্যাটফর্ম
কাঁচা কোয়েরি সংজ্ঞায়িত করুন
@Dao
interface TodoDao {
@RawQuery
suspend fun getTodos(query: RoomRawQuery): List<TodoEntity>
}
এরপর রানটাইমে একটি কোয়েরি তৈরি করতে একটি RoomRawQuery ব্যবহার করা যেতে পারে:
suspend fun AppDatabase.getTodosWithLowercaseTitle(title: String): List<TodoEntity> {
val query = RoomRawQuery(
sql = "SELECT * FROM TodoEntity WHERE title = ?",
onBindStatement = {
it.bindText(1, title.lowercase())
}
)
return todoDao().getTodos(query)
}
শুধুমাত্র অ্যান্ড্রয়েডের জন্য
কাঁচা কোয়েরি সংজ্ঞায়িত করুন
@Dao
interface TodoDao {
@RawQuery
suspend fun getTodos(query: SupportSQLiteQuery): List<TodoEntity>
}
এরপর রানটাইমে একটি কোয়েরি তৈরি করতে SimpleSQLiteQuery ব্যবহার করা যেতে পারে:
suspend fun AndroidOnlyDao.getTodosWithLowercaseTitle(title: String): List<TodoEntity> {
val query = SimpleSQLiteQuery(
query = "SELECT * FROM TodoEntity WHERE title = ?",
bindArgs = arrayOf(title.lowercase())
)
return getTodos(query)
}
ব্লকিং DAO ফাংশনগুলিকে রূপান্তর করুন
রুম (Room) কোটলিনের একাধিক প্ল্যাটফর্মের জন্য প্রদত্ত বৈশিষ্ট্য-সমৃদ্ধ অ্যাসিঙ্ক্রোনাস kotlinx.coroutines লাইব্রেরি থেকে সুবিধা লাভ করে। সর্বোত্তম কার্যকারিতার জন্য, একটি KMP প্রোজেক্টে কম্পাইল করা DAO-গুলোর ক্ষেত্রে suspend ফাংশন বাধ্যতামূলক করা হয়; তবে বিদ্যমান কোডবেসের সাথে ব্যাকওয়ার্ড কম্প্যাটিবিলিটি বজায় রাখার জন্য androidMain এ ইমপ্লিমেন্ট করা DAO-গুলোর ক্ষেত্রে এটি প্রযোজ্য নয়। KMP-এর জন্য রুম (Room) ব্যবহার করার সময়, নন-অ্যান্ড্রয়েড প্ল্যাটফর্মের জন্য কম্পাইল করা সমস্ত DAO ফাংশনকে suspend ফাংশন হতে হবে।
কোটলিন মাল্টিপ্ল্যাটফর্ম
প্রশ্ন স্থগিত করা
@Query("SELECT * FROM Todo")
suspend fun getAllTodos(): List<Todo>
লেনদেন স্থগিত করা
@Transaction
suspend fun transaction() { … }
শুধুমাত্র অ্যান্ড্রয়েডের জন্য
ব্লকিং কোয়েরি
@Query("SELECT * FROM Todo")
fun getAllTodos(): List<Todo>
লেনদেন ব্লক করা
@Transaction
fun blockingTransaction() { … }
রিঅ্যাক্টিভ টাইপগুলোকে ফ্লো-তে রূপান্তর করুন
সব DAO ফাংশনকে সাসপেন্ড ফাংশন হওয়ার প্রয়োজন নেই। যেসব DAO ফাংশন LiveData বা RxJava-এর Flowable মতো রিঅ্যাক্টিভ টাইপ রিটার্ন করে, সেগুলোকে সাসপেন্ড ফাংশনে রূপান্তর করা উচিত নয়। তবে, LiveData মতো কিছু টাইপ KMP-কম্প্যাটিবল নয়। রিঅ্যাক্টিভ রিটার্ন টাইপযুক্ত DAO ফাংশনগুলোকে অবশ্যই কো-রুটিন ফ্লো-তে মাইগ্রেট করতে হবে।
কোটলিন মাল্টিপ্ল্যাটফর্ম
প্রতিক্রিয়াশীল ধরণের Flows
@Query("SELECT * FROM Todo")
fun getTodosFlow(): Flow<List<Todo>>
শুধুমাত্র অ্যান্ড্রয়েডের জন্য
LiveData বা RxJava-এর Flowable মতো রিঅ্যাক্টিভ টাইপ
@Query("SELECT * FROM Todo")
fun getTodosLiveData(): LiveData<List<Todo>>
লেনদেন এপিআই রূপান্তর করুন
Room KMP-এর ডাটাবেস ট্রানজ্যাকশন API-গুলো রাইটিং ( useWriterConnection ) এবং রিডিং ( useReaderConnection ) ট্রানজ্যাকশনের মধ্যে পার্থক্য করতে পারে।
কোটলিন মাল্টিপ্ল্যাটফর্ম
val database: RoomDatabase = …
database.useWriterConnection { transactor ->
transactor.immediateTransaction {
// perform database operations in transaction
}
}
শুধুমাত্র অ্যান্ড্রয়েডের জন্য
val database: RoomDatabase = …
database.withTransaction {
// perform database operations in transaction
}
লেনদেন লিখুন
একাধিক কোয়েরি যেন অ্যাটমিকভাবে ডেটা লেখে, তা নিশ্চিত করতে রাইট ট্রানজ্যাকশন ব্যবহার করুন, যাতে রিডাররা ধারাবাহিকভাবে ডেটা অ্যাক্সেস করতে পারে। আপনি তিনটি ট্রানজ্যাকশন টাইপের যেকোনো একটির সাথে useWriterConnection ব্যবহার করে এটি করতে পারেন:
immediateTransaction: রাইট-অহেড লগিং (WAL) মোডে (যা ডিফল্ট), এই ধরনের ট্রানজ্যাকশন শুরু হওয়ার সময় একটি লক অর্জন করে, কিন্তু রিডাররা পড়া চালিয়ে যেতে পারে। বেশিরভাগ ক্ষেত্রেই এটিই পছন্দের বিকল্প।deferredTransaction): এই ট্রানজ্যাকশনটি প্রথম রাইট স্টেটমেন্টের আগে কোনো লক অর্জন করবে না। যখন আপনি নিশ্চিত নন যে ট্রানজ্যাকশনের মধ্যে কোনো রাইট অপারেশনের প্রয়োজন হবে কিনা, তখন অপটিমাইজেশন হিসেবে এই ধরনের ট্রানজ্যাকশন ব্যবহার করুন। উদাহরণস্বরূপ, যদি আপনি শুধুমাত্র প্লেলিস্টের নাম দিয়ে প্লেলিস্ট থেকে গান ডিলিট করার জন্য একটি ট্রানজ্যাকশন শুরু করেন এবং প্লেলিস্টটির কোনো অস্তিত্ব না থাকে, তাহলে কোনো রাইট (ডিলিট) অপারেশনের প্রয়োজন নেই।exclusiveTransaction: এই মোডটি WAL মোডেরimmediateTransactionএর মতোই কাজ করে। অন্যান্য জার্নালিং মোডে, এটি ট্রানজ্যাকশন চলাকালীন অন্য ডাটাবেস কানেকশনগুলোকে ডাটাবেস থেকে ডেটা পড়া থেকে বিরত রাখে।
লেনদেন পড়ুন
ডাটাবেস থেকে ধারাবাহিকভাবে একাধিকবার ডেটা পড়ার জন্য রিড ট্রানজ্যাকশন ব্যবহার করুন। উদাহরণস্বরূপ, যখন আপনার দুই বা ততোধিক পৃথক কোয়েরি থাকে এবং আপনি কোনো JOIN ক্লজ ব্যবহার করেন না। রিডার কানেকশনে শুধুমাত্র ডিফার্ড ট্রানজ্যাকশন অনুমোদিত। রিডার কানেকশনে ইমিডিয়েট বা এক্সক্লুসিভ ট্রানজ্যাকশন শুরু করার চেষ্টা করলে একটি এক্সেপশন থ্রো হবে, কারণ এগুলোকে 'রাইট' অপারেশন হিসেবে গণ্য করা হয়।
val database: RoomDatabase = …
database.useReaderConnection { transactor ->
transactor.deferredTransaction {
// perform database operations in transaction
}
}
কোটলিন মাল্টিপ্ল্যাটফর্মে উপলব্ধ নয়
অ্যান্ড্রয়েডের জন্য উপলব্ধ কিছু এপিআই কোটলিন মাল্টিপ্ল্যাটফর্মে পাওয়া যায় না।
কোয়েরি কলব্যাক
কোয়েরি কলব্যাক কনফিগার করার জন্য নিম্নলিখিত এপিআইগুলো সাধারণভাবে উপলব্ধ নয় এবং তাই অ্যান্ড্রয়েড ছাড়া অন্য কোনো প্ল্যাটফর্মে এগুলো পাওয়া যায় না।
-
RoomDatabase.Builder.setQueryCallback -
RoomDatabase.QueryCallback
আমরা Room-এর ভবিষ্যৎ কোনো সংস্করণে কোয়েরি কলব্যাকের সুবিধা যোগ করার পরিকল্পনা করছি।
RoomDatabase.Builder.setQueryCallback নামক কোয়েরি কলব্যাকসহ একটি RoomDatabase কনফিগার করার এপিআই এবং RoomDatabase.QueryCallback নামক কলব্যাক ইন্টারফেসটি সাধারণভাবে উপলব্ধ নয় এবং তাই অ্যান্ড্রয়েড ছাড়া অন্য কোনো প্ল্যাটফর্মে এটি পাওয়া যায় না।
স্বয়ংক্রিয়ভাবে বন্ধ হওয়া ডাটাবেস
টাইমআউটের পর স্বয়ংক্রিয়ভাবে বন্ধ করার এপিআই, RoomDatabase.Builder.setAutoCloseTimeout , শুধুমাত্র অ্যান্ড্রয়েডে উপলব্ধ এবং অন্য কোনো প্ল্যাটফর্মে পাওয়া যায় না।
প্রি-প্যাকেজ ডেটাবেস
বিদ্যমান ডেটাবেস (অর্থাৎ একটি প্রি-প্যাকেজড ডেটাবেস) ব্যবহার করে একটি RoomDatabase তৈরি করার জন্য নিম্নলিখিত API-গুলি সাধারণভাবে উপলব্ধ নয় এবং তাই Android ছাড়া অন্য প্ল্যাটফর্মে পাওয়া যায় না। এই API-গুলি হলো:
-
RoomDatabase.Builder.createFromAsset -
RoomDatabase.Builder.createFromFile -
RoomDatabase.Builder.createFromInputStream -
RoomDatabase.PrepackagedDatabaseCallback
আমরা Room-এর ভবিষ্যৎ কোনো সংস্করণে আগে থেকে তৈরি করা ডেটাবেসের জন্য সমর্থন যোগ করার পরিকল্পনা করছি।
একাধিক ইনস্ট্যান্সের অবৈধকরণ
মাল্টি-ইনস্ট্যান্স ইনভ্যালিডেশন চালু করার এপিআই, RoomDatabase.Builder.enableMultiInstanceInvalidation , শুধুমাত্র অ্যান্ড্রয়েডে উপলব্ধ এবং সাধারণ বা অন্যান্য প্ল্যাটফর্মে উপলব্ধ নয়।
আপনার জন্য প্রস্তাবিত
- দ্রষ্টব্য: জাভাস্ক্রিপ্ট বন্ধ থাকলেও লিঙ্কের লেখা প্রদর্শিত হয়।
- বিদ্যমান অ্যাপগুলিকে রুম কেএমপি কোডল্যাবে স্থানান্তর করুন
- KMP কোডল্যাব দিয়ে শুরু করুন
- Room ব্যবহার করে স্থানীয় ডাটাবেসে ডেটা সংরক্ষণ করুন