Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
💾 Data, Network और Architecture  ·  Lesson 30

Room Database (SQLite)

Room क्या है?

Room SQLite (हर Android phone में built-in database) के ऊपर Jetpack की library है। आप Kotlin classes से tables और annotations से queries describe करते हैं; Room आपकी SQL compile time पर check करता है और boring code generate करता है।

UI (Fragment)data observe करता हैViewModelrepository call करता हैRepositorysingle source of truthDAO (@Dao)SQL queriesRoom database → SQLite filestudent_diary.db
App में Room कहाँ है
notes🔑 id INTEGERtitle TEXTcontent TEXTsubject TEXTpriority INTEGERdueAt INTEGER?isDone INTEGERisFavorite INTEGERimagePath TEXT?createdAt INTEGER
Student Diary table

Step 1: Dependencies (KSP)

TOML + Kotlin DSL
# gradle/libs.versions.toml
ksp = "2.0.21-1.0.28"
room = "2.6.1"
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }        # under [plugins]

// app/build.gradle.kts
plugins { alias(libs.plugins.ksp) }
dependencies {
    implementation(libs.androidx.room.runtime)
    implementation(libs.androidx.room.ktx)       // coroutines + Flow support
    ksp(libs.androidx.room.compiler)             // generates the DAO code
}

Step 2: Entity = table

Kotlin – data/Note.kt
package com.codingeasily.studentdiary.data

import androidx.room.Entity
import androidx.room.PrimaryKey

/** One row of the "notes" table. */
@Entity(tableName = "notes")
data class Note(
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    val title: String,
    val content: String = "",
    val subject: String = "General",
    val priority: Int = PRIORITY_MEDIUM,      // 0 = low, 1 = medium, 2 = high
    val dueAt: Long? = null,                  // reminder time in millis, null = no reminder
    val isDone: Boolean = false,
    val isFavorite: Boolean = false,
    val imagePath: String? = null,            // photo copied into app storage
    val createdAt: Long = System.currentTimeMillis()
) {
    companion object {
        const val PRIORITY_LOW = 0
        const val PRIORITY_MEDIUM = 1
        const val PRIORITY_HIGH = 2
    }
}

/** Result of a GROUP BY query: how many notes each subject has. */
data class SubjectCount(val subject: String, val total: Int)
SQL – Room की बनाई table
-- What Room creates for the Note entity
CREATE TABLE notes (
  id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  title TEXT NOT NULL,
  content TEXT NOT NULL,
  subject TEXT NOT NULL,
  priority INTEGER NOT NULL,
  dueAt INTEGER,                -- Long? → nullable
  isDone INTEGER NOT NULL,      -- Boolean → 0/1
  isFavorite INTEGER NOT NULL,
  imagePath TEXT,
  createdAt INTEGER NOT NULL
);

Step 3: DAO = queries

Kotlin – data/NoteDao.kt
package com.codingeasily.studentdiary.data

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import kotlinx.coroutines.flow.Flow

/** All SQL for the notes table lives here. Room generates the implementation. */
@Dao
interface NoteDao {

    // Flow = the UI is updated automatically whenever the table changes
    @Query("SELECT * FROM notes ORDER BY isDone ASC, priority DESC, createdAt DESC")
    fun getAll(): Flow<List<Note>>

    @Query("SELECT * FROM notes WHERE isDone = :done ORDER BY priority DESC, createdAt DESC")
    fun getByDone(done: Boolean): Flow<List<Note>>

    @Query("SELECT * FROM notes WHERE isFavorite = 1 ORDER BY createdAt DESC")
    fun getFavorites(): Flow<List<Note>>

    @Query("SELECT * FROM notes WHERE subject = :subject ORDER BY createdAt DESC")
    fun getBySubject(subject: String): Flow<List<Note>>

    @Query("SELECT * FROM notes WHERE title LIKE '%' || :q || '%' OR content LIKE '%' || :q || '%' ORDER BY createdAt DESC")
    fun search(q: String): Flow<List<Note>>

    @Query("SELECT subject, COUNT(*) AS total FROM notes GROUP BY subject ORDER BY total DESC")
    fun subjectCounts(): Flow<List<SubjectCount>>

    @Query("SELECT COUNT(*) FROM notes")
    fun countAll(): Flow<Int>

    @Query("SELECT COUNT(*) FROM notes WHERE isDone = 1")
    fun countDone(): Flow<Int>

    @Query("SELECT * FROM notes WHERE id = :id")
    suspend fun getById(id: Long): Note?

    @Insert
    suspend fun insert(note: Note): Long

    @Update
    suspend fun update(note: Note)

    @Delete
    suspend fun delete(note: Note)

    @Query("DELETE FROM notes WHERE isDone = 1")
    suspend fun deleteDone(): Int
}
Return typeमतलब
Flow<List<Note>>Observed: हर बदलाव पर फिर emit (suspend नहीं)
suspend fun … : Note?Coroutine के अंदर एक बार पढ़ना
suspend fun insert(…): Longनई row की id लौटाता है
suspend fun deleteDone(): IntDelete हुई rows की संख्या

Step 4: Database class

Kotlin – data/AppDatabase.kt
package com.codingeasily.studentdiary.data

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase

@Database(entities = [Note::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {

    abstract fun noteDao(): NoteDao

    companion object {
        @Volatile private var INSTANCE: AppDatabase? = null

        /** Singleton: the whole app shares one database connection. */
        fun get(context: Context): AppDatabase =
            INSTANCE ?: synchronized(this) {
                INSTANCE ?: Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "student_diary.db"
                ).build().also { INSTANCE = it }
            }
    }
}

Step 5: Repository

Kotlin – data/NoteRepository.kt
package com.codingeasily.studentdiary.data

import kotlinx.coroutines.flow.Flow

/**
 * The single source of truth for notes. ViewModels talk to the repository,
 * never directly to the DAO. Later you could add a network source here.
 */
class NoteRepository(private val dao: NoteDao) {
    val allNotes: Flow<List<Note>> = dao.getAll()
    val pendingNotes: Flow<List<Note>> = dao.getByDone(false)
    val doneNotes: Flow<List<Note>> = dao.getByDone(true)
    val favorites: Flow<List<Note>> = dao.getFavorites()
    val subjectCounts: Flow<List<SubjectCount>> = dao.subjectCounts()
    val countAll: Flow<Int> = dao.countAll()
    val countDone: Flow<Int> = dao.countDone()

    fun bySubject(subject: String) = dao.getBySubject(subject)
    fun search(q: String) = dao.search(q)

    suspend fun get(id: Long) = dao.getById(id)
    suspend fun save(note: Note): Long =
        if (note.id == 0L) dao.insert(note) else { dao.update(note); note.id }
    suspend fun delete(note: Note) = dao.delete(note)
    suspend fun deleteDone() = dao.deleteDone()
}

UI से use करना

Kotlin
// Quick test inside an Activity (later this moves into a ViewModel)
val dao = AppDatabase.get(this).noteDao()

lifecycleScope.launch {
    dao.insert(Note(title = "Maths homework", subject = "Maths", priority = Note.PRIORITY_HIGH))
}

lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        dao.getAll().collect { notes ->               // runs again after every change
            adapter.submitList(notes)
        }
    }
}
FragmentDAOSQLitegetAll() collectSELECT …3 notes की listinsert(new note) (coroutine)INSERTFlow अपने आप 4 notes की list भेजता है
एक बार insert — हर observer update

अपना data देखें: App Inspection

App चलाइए, फिर View → Tool Windows → App Inspection → Database Inspector खोलिए। notes table browse कर सकते हैं और live SQL queries भी चला सकते हैं।

Table बदलना (migrations)

Kotlin
// Version 2 adds a "color" column to notes
@Database(entities = [Note::class], version = 2, exportSchema = false)
abstract class AppDatabase : RoomDatabase() { /* … */ }

val MIGRATION_1_2 = object : Migration(1, 2) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("ALTER TABLE notes ADD COLUMN color INTEGER NOT NULL DEFAULT 0")
    }
}

Room.databaseBuilder(context, AppDatabase::class.java, "student_diary.db")
    .addMigrations(MIGRATION_1_2)
    .build()

// While developing only (deletes all data!):  .fallbackToDestructiveMigration()

आम गलतियाँ

  • Main thread पर non-suspend DAO function → "Cannot access database on the main thread"।
  • version बढ़ाए बिना Entity बदलना → crash "Room cannot verify the data integrity"।
  • हर screen में नया database instance → memory बर्बाद; singleton use करें।
  • @Query में column names के typos → Room compile error दिखाता है (यह अच्छी बात है — पढ़ें)।

सारांश

  • @Entity (table) + @Dao (queries) + @Database (singleton) + Repository।
  • अपने आप update होने वाली lists के लिए Flow; एक बार read/write के लिए suspend।
  • Schema बदले तो version बढ़ाएँ और Migration जोड़ें।
✅ Practice

Expense(id, title, amount, category, date) table बनाइए जिसमें सारे expenses (Flow), हर category का total (GROUP BY) और delete की queries हों। List RecyclerView में दिखाइए जो हर insert के बाद update हो।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

Room queries main thread पर क्यों नहीं चला सकते?
Database काम में समय लग सकता है और UI अटक जाएगा। Main-thread access पर Room exception देता है। Coroutines में suspend functions use करें या Flow लौटाएँ।
DAO से Flow लौटाने का क्या फ़ायदा?
Table बदलते ही Room query दोबारा चलाकर नई list भेजता है, इसलिए insert, update या delete के बाद RecyclerView अपने आप update होता है।
Room के लिए KSP या kapt?
KSP use करें। यह तेज़ है और Kotlin के साथ Room के लिए recommended processor है; kapt maintenance mode में है।
← Android Tutorial (Kotlin)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicMVVM: ViewModel, LiveData और Flow आपकी प्रगति: 30 / 43 (70%) · Lesson 31 / 43 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें