Ang Room ay isang ORM library mula sa Android Jetpack na nagbibigay ng abstraction layer sa ibabaw ng SQLite para sa pagtatrabaho sa mga lokal na database sa Android. Ayon sa opisyal na dokumentasyon Android Developers, 2025, ang Room ay awtomatikong bumubuo ng mga implementasyon ng DAO batay sa mga annotation sa panahon ng compilation, na nag-aalis ng humigit-kumulang 70% ng boilerplate code kumpara sa direktang paggamit ng SQLiteOpenHelper. Ang library ay nagsasagawa ng pag-verify ng mga SQL query sa yugto ng compilation, na nagpapahintulot na matukoy ang mga syntax error bago patakbuhin ang app sa device.
Mga Pangunahing Punto
Room ay isang ORM library mula sa Android Jetpack, na ginawa ng Google upang pasimplehin ang pagtatrabaho sa mga lokal na SQLite database sa Android platform. Nagbibigay ito ng mga annotation para sa paglalarawan ng schema ng data at awtomatikong bumubuo ng implementasyon ng mga DAO interface sa yugto ng compilation. Hindi tulad ng direktang paggamit ng SQLiteOpenHelper, pinapalaya ng Room ang developer mula sa pagsulat ng malaking halaga ng boilerplate code para sa paglikha, pagbubukas at pamamahala ng koneksyon sa database.
Ang library ay ipinakilala sa Google I/O 2017 bilang bahagi ng mga architectural component ng Android. Mula noon, ang Room ay naging de facto na pamantayan para sa lokal na pag-iimbak ng data, na nalampasan sa kasikatan ang mga solusyon tulad ng GreenDAO at Realm para sa Android. Ayon sa Google, ang library ay ginagamit sa higit sa 60% ng mga app na nai-publish sa Google Play na gumagana sa lokal na data sa device.
Pangunahing tampok — pag-verify ng mga SQL query sa yugto ng compilation gamit ang annotation processor. Kung ang developer ay magkamali sa SQL command, halimbawa, tumukoy ng hindi umiiral na pangalan ng column, ang compilation ay magtatapos sa error bago i-install ang app. Ito ay lubhang naiiba mula sa SQLiteOpenHelper approach, kung saan ang mga ganitong error ay natutukoy lamang sa runtime, madalas sa produksyon.
Ang SQLite ay sumusuporta lamang sa limang uri ng data: TEXT, INTEGER, REAL, BLOB at NULL. Gayunpaman, sa Java at Kotlin ay ginagamit ang mga kumplikadong uri: Date, List, Enum at mga custom na object. Para sa pag-iimbak ng mga ito, ang Room ay nagbibigay ng mekanismong TypeConverters — mga static na pamamaraan na nagko-convert ng kumplikadong uri sa primitibong uri na naiintindihan ng SQLite. Halimbawa, ang Date object ay na-convert sa Long (timestamp), at ang List<String> sa JSON string sa pamamagitan ng Gson o Moshi.
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
val db = Room
.databaseBuilder(context, AppDatabase::class.java, "app-db")
.build()
Upang ideklara ang converter, sapat na magdagdag ng @TypeConverter annotation sa isang static na pamamaraan at tukuyin ang converter class sa @TypeConverters annotation sa antas ng database. Awtomatikong inilalapat ng Room ang converter kapag binabasa at sinusulat ang kaukulang uri sa bawat SQL query nang hindi manu-manong tinatawag ang mga conversion method.
Room ay binubuo ng tatlong pangunahing bahagi: Entity, DAO at Database. Bawat isa ay gumaganap ng mahigpit na tinukoy na papel at na-annotate ng kaukulang annotation. Sama-sama silang bumubuo ng isang kumpletong layer ng pag-access ng data na naghihiwalay sa business logic ng app mula sa mga detalye ng implementasyon ng SQLite.
Entity ay isang klase ng data na naglalarawan ng istraktura ng isang talahanayan sa database. Ang bawat field ng klase ay tumutugma sa isang column ng talahanayan, at ang bawat row sa database ay tumutugma sa isang instance ng klase. Ang @Entity annotation ay nagsasabi sa Room na ang klase ay isang talahanayan. Ang field na may @PrimaryKey annotation ay tumutukoy sa pangunahing key, na maaaring auto-increment o composite. Para sa relasyon sa pagitan ng mga talahanayan, ginagamit ang @ForeignKey, na nagsisiguro ng integridad ng data sa antas ng database.
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
@ColumnInfo(name = "full_name")
val name: String,
val age: Int,
val email: String
)
DAO (Data Access Object) ay isang interface o abstract class na nagdedeklara ng mga operasyon para sa pagtatrabaho sa data: pagpasok, pagbasa, pag-update at pagtanggal. Ang bawat operasyon ay na-annotate ng @Insert, @Query, @Update o @Delete. Awtomatikong bumubuo ang Room ng implementasyon ng interface na ito sa yugto ng compilation. Ang partikular na halaga ay taglay ng @Query annotation, na tumatanggap ng SQL query bilang string at sinusuri ang kawastuhan nito sa yugto ng build.
@Dao
interface UserDao {
@Insert
suspend fun insert(user: User): Long
@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUserById(userId: Int): User?
@Query("SELECT * FROM users")
fun getAllUsers(): Flow<List<User>>
@Delete
suspend fun delete(user: User)
}
Database ay isang abstract class na nagmamana ng RoomDatabase, na nagsisilbing entry point sa database. Naglalaman ito ng listahan ng lahat ng Entity at nagbibigay ng mga abstract na pamamaraan para sa pagkuha ng DAO. Ang klase ay na-annotate ng @Database, kung saan tinutukoy ang bersyon ng schema at listahan ng mga entity. Ang paglikha ng instance ng database ay ginagawa sa pamamagitan ng Room.databaseBuilder na may pagtukoy sa konteksto ng app, pangalan ng file at klase ng Database.
Room ay hindi pumapalit sa SQLite, kundi gumagana sa ibabaw nito bilang abstraction layer. Ang panloob na arkitektura ay may kasamang annotation processor, code generator at connection pool. Sa yugto ng compilation, sinusuri ng annotation processor ang mga klase ng Entity, DAO at Database, pagkatapos ay bumubuo ng mga implementasyon na klase na may suffix na _Impl. Lahat ng nabuong klase ay inilalagay sa build package at hindi direktang nakikita ng developer.
Ang pagbuo ng code sa yugto ng compilation — sentral na mekanismo ng Room. Para sa bawat DAO interface, nabubuo ang isang klase na may kumpletong implementasyon ng lahat ng na-annotate na pamamaraan. Ang mga SQL query mula sa @Query annotation ay sinusuri para sa kawastuhan: itinutugma ng processor ang mga pangalan ng column sa mga field ng Entity at sinusuri ang syntax ng SQL. Kapag may nakitang error, ang compilation ay naaantala na may malinaw na mensahe. Ito ay imposible kapag gumagamit ng raw SQLiteOpenHelper, kung saan ang mga error ay lilitaw lamang sa runtime.
Ang proseso ng pagbuo ay may kasamang tatlong yugto. Una — pagpapatunay ng schema: sinusuri ng processor kung ang lahat ng klase na nakalista sa @Database ay wastong Entity. Ikalawa — pagbuo ng katawan ng DAO: para sa bawat pamamaraan, nilikha ang isang implementasyon gamit ang panloob na RoomSQLiteQuery object na nagsasagawa ng mga prepared query. Ikatlo — pagbuo ng Database_Impl class, na nagpapatupad ng paglikha at pagbubukas ng database pati na rin ang pagsisimula ng lahat ng DAO object.
class UserDao_Impl(private val __db: RoomDatabase) : UserDao {
private val __insertionAdapter = __db
.createInsertionAdapter(User::class, 0)
override suspend fun insert(user: User): Long {
__db.assertNotSuspendingTransaction()
return __db.runInTransaction {
__insertionAdapter.insertAndReturnId(user)
}
}
}
Ang Room ay hindi lumilikha ng hiwalay na thread pool para sa mga operasyon ng database. Bilang default, ang mga query ay isinasagawa sa tumatawag na thread na may isang limitasyon: ang pagbasa at pagsulat ay humaharang sa thread. Para sa asynchronous na trabaho, ang Room ay sumasama sa Kotlin coroutines sa pamamagitan ng suspend function, sa LiveData sa pamamagitan ng mga return value at sa Flow sa pamamagitan ng reactive wrapper. Ito ay nagbibigay sa developer ng flexibility sa pagpili ng architectural solution para sa isang partikular na gawain.
Tingnan natin ang isang praktikal na halimbawa ng paglikha ng app para sa pag-iimbak ng mga tala gamit ang Room. Ang app ay naglalaman ng isang talahanayan na Note na may mga field na id, title, content at timestamp. Ang user ay makakapagdagdag, makakatingin at makakapagtanggal ng mga tala. Para sa demonstrasyon, ginagamit ang mga coroutine para sa asynchronous na mga operasyon.
Upang ikonekta ang Room sa isang Android project, kailangan magdagdag ng mga dependency sa build.gradle file ng module ng app. Ang Room ay nangangailangan ng tatlong bahagi: runtime library, kapt annotation processor at opsyonal na suporta para sa coroutine. Ang bersyon ng library ay tinukoy sa variable na room_version para sa kadalian ng pag-update. Simula sa Room 2.4.0, ang KSP ay sinusuportahan bilang alternatibo sa kapt na may mas mataas na bilis ng build.
dependencies {
def room_version = "2.6.1"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
// Opsyonal: pagsubok
testImplementation "androidx.room:room-testing:$room_version"
}
Pagkatapos i-configure ang mga dependency, tatlong file ang nilikha: Note Entity, NoteDao interface at AppDatabase class. Ang Entity Note ay naglalaman ng mga field na may @PrimaryKey at @ColumnInfo annotation. Ang DAO ay nagbibigay ng mga pamamaraan para sa pagpasok, pagkuha ng listahan at pagtanggal. Ang Database ay nag-uugnay ng Entity at DAO sa pamamagitan ng @Database annotation.
@Entity(tableName = "notes")
data class Note(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
val title: String,
val content: String,
@ColumnInfo(name = "created_at")
val timestamp: Long = System.currentTimeMillis()
)
@Dao
interface NoteDao {
@Insert
suspend fun insert(note: Note)
@Query("SELECT * FROM notes ORDER BY created_at DESC")
fun getAllNotes(): Flow<List<Note>>
@Delete
suspend fun delete(note: Note)
}
Ang file na AppDatabase ay idineklara bilang abstract class na nagmamana ng RoomDatabase. Sa @Database annotation, lahat ng Entity ng kasalukuyang bersyon at numero ng bersyon ng schema ay tinukoy. Para sa pagkuha ng instance, ginagamit ang singleton pattern sa pamamagitan ng build method ng Room.databaseBuilder na may konteksto ng app. Ang pag-cache ng database instance ay pumipigil sa maramihang paglikha na maaaring humantong sa pagtagas ng memorya.
Mga migration sa Room ay isang mekanismo para sa pagbabago ng schema ng database kapag nag-a-update ng app nang hindi nawawala ang umiiral na data. Kapag nag-install ang user ng bagong bersyon na may binagong Entity, nade-detect ng Room ang hindi pagkakatugma ng bersyon at isinasagawa ang tinukoy na mga hakbang sa migration. Kung walang migration, ang database ay tatanggalin at muling lilikhain, na magreresulta sa pagkawala ng lahat ng naka-save na data ng user.
Ang migration ay inilalarawan ng Migration class, na tumatanggap ng simula at panghuling bersyon ng database. Sa loob ng migrate method, isinasagawa ang SQL query na ALTER TABLE o CREATE TABLE upang baguhin ang schema. Ang Room ay hindi awtomatikong matukoy ang mga pagbabago sa schema — ang developer ay dapat na manu-manong sumulat ng migration para sa bawat pagbabago ng Entity. Simula sa bersyon ng Room 2.4.0, ang eksperimental na function na autoMigrations ay magagamit para sa awtomatikong pagbuo ng mga migration.
Ang function na autoMigrations ay nagpapahintulot sa Room na awtomatikong bumuo ng mga migration batay sa mga pagkakaiba sa pagitan ng mga bersyon ng Entity. Upang magamit ito, sapat na magdagdag ng @AutoMigration annotation sa @Database at tukuyin ang pag-export ng schema sa JSON. Inihahambing ng Room ang mga schema ng mga katabing bersyon at bumubuo ng mga kinakailangang ALTER query. Gayunpaman, ang autoMigrations ay sumusuporta lamang sa backward-compatible na mga pagbabago: pagdaragdag ng mga column, paglikha ng mga index at pagbabago ng mga uri na may katugmang conversion.
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL(
"ALTER TABLE users ADD COLUMN phone TEXT"
)
}
}
val db = Room
.databaseBuilder(context, AppDatabase::class.java, "app-db")
.addMigrations(MIGRATION_1_2)
.build()
Kapag nagdaragdag ng mga kumplikadong pagbabago, tulad ng pagpapalit ng pangalan ng mga column o pagsasama ng mga talahanayan, kinakailangan ang manu-manong migration gamit ang mga pansamantalang talahanayan. Karaniwang senaryo: lumikha ng pansamantalang talahanayan na may lumang schema, kopyahin ang data mula sa lumang talahanayan patungo sa bago na may mga conversion, tanggalin ang lumang talahanayan at palitan ang pangalan ng pansamantalang. Room ay ginagarantiyahan na ang lahat ng migration ay isinasagawa sa isang transaksyon, at sa paglitaw ng error, ang mga pagbabago ay ganap na ibinabalik.
Mga Madalas Itanong
Room ay nagbibigay ng ORM abstraction na may mga annotation at SQL verification sa yugto ng compilation, samantalang ang SQLiteOpenHelper ay nangangailangan ng manu-manong pagsulat ng lahat ng query at pamamahala ng koneksyon. Awtomatikong bumubuo ang Room ng code para sa CRUD operations at sumasama sa mga architectural component ng Android, kabilang ang LiveData at Flow.
Room ay sumusuporta sa lahat ng primitibong uri ng Java: Int, Long, Boolean, Float, Double, pati na rin ang String, ByteArray at Date. Para sa mga kumplikadong uri tulad ng List o Enum, ginagamit ang TypeConverters — mga static na conversion method na nagko-convert ng hindi karaniwang mga uri sa mga format na sinusuportahan ng SQLite.
Oo, ang Room ay sumusuporta sa synchronous na mga tawag nang walang coroutine, ngunit hinaharangan nila ang thread kung saan sila isinasagawa. Para sa asynchronous na trabaho, maaaring gamitin ang LiveData o RxJava sa halip na coroutine. Inirerekomenda ng Google ang paggamit ng coroutine bilang pangunahing paraan ng asynchronous na pag-access sa data sa mga bagong proyekto.
Kung ang Room ay nakakita ng hindi pagkakatugma ng bersyon ng database at hindi makahanap ng angkop na migration, bilang default ay magaganap ang IllegalStateException na may paglalarawan ng error. Maaaring i-override ng developer ang pag-uugaling ito gamit ang fallbackToDestructiveMigration method, na tatanggalin ang umiiral na database at lilikha ng bago na may pagkawala ng lahat ng data.
Room ay sumusuporta sa mga relasyon sa pamamagitan ng mga nested object na may @Embedded annotation at sa pamamagitan ng relation class na may @Relation annotation. Para sa mga kumplikadong query na may pagsasama ng mga talahanayan, ginagamit ang mga custom na POJO class na ang mga field ay pinupunan mula sa mga resulta ng @Query na may JOIN operator sa SQL.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din