Room adalah pustaka ORM dari Android Jetpack yang menyediakan lapisan abstraksi di atas SQLite untuk bekerja dengan basis data lokal di Android. Menurut dokumentasi resmi Android Developers, 2025, Room secara otomatis menghasilkan implementasi DAO berdasarkan anotasi selama kompilasi, yang menghilangkan sekitar 70% kode boilerplate dibandingkan dengan penggunaan langsung SQLiteOpenHelper. Pustaka ini melakukan validasi kueri SQL pada tahap kompilasi, memungkinkan deteksi kesalahan sintaks sebelum aplikasi dijalankan di perangkat.
Poin Utama
Room adalah pustaka ORM dari Android Jetpack, dibuat oleh Google untuk menyederhanakan pekerjaan dengan basis data lokal SQLite di platform Android. Pustaka ini menyediakan anotasi untuk mendeskripsikan skema data dan secara otomatis menghasilkan implementasi antarmuka DAO pada tahap kompilasi. Berbeda dengan penggunaan langsung SQLiteOpenHelper, Room membebaskan pengembang dari menulis sejumlah besar kode boilerplate untuk membuat, membuka, dan mengelola koneksi ke basis data.
Pustaka ini diperkenalkan di Google I/O 2017 sebagai bagian dari komponen arsitektur Android. Sejak saat itu Room telah menjadi standar de facto untuk penyimpanan data lokal, mengungguli solusi seperti GreenDAO dan Realm untuk Android dalam hal popularitas. Menurut Google, pustaka ini digunakan di lebih dari 60% aplikasi yang dipublikasikan di Google Play yang bekerja dengan data lokal di perangkat.
Fitur utama — validasi kueri SQL pada tahap kompilasi menggunakan pemroses anotasi. Jika pengembang melakukan kesalahan dalam perintah SQL, misalnya menyebutkan nama kolom yang tidak ada, kompilasi akan berakhir dengan kesalahan sebelum instalasi aplikasi. Ini sangat berbeda dengan pendekatan SQLiteOpenHelper, di mana kesalahan semacam itu hanya terdeteksi saat runtime, seringkali di produksi.
SQLite hanya mendukung lima tipe data: TEXT, INTEGER, REAL, BLOB dan NULL. Namun di Java dan Kotlin digunakan tipe kompleks: Date, List, Enum dan objek kustom. Untuk menyimpannya, Room menyediakan mekanisme TypeConverters — metode statis yang mengubah tipe kompleks menjadi tipe primitif yang dapat dipahami SQLite. Misalnya, objek Date dikonversi menjadi Long (timestamp), dan List<String> menjadi string JSON melalui Gson atau 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()
Untuk mendeklarasikan konverter, cukup tambahkan anotasi @TypeConverter ke metode statis dan tentukan kelas konverter dalam anotasi @TypeConverters di tingkat basis data. Room secara otomatis menerapkan konverter saat membaca dan menulis tipe yang sesuai di setiap kueri SQL tanpa memanggil metode konversi secara manual.
Room terdiri dari tiga komponen utama: Entity, DAO dan Database. Masing-masing menjalankan peran yang ditentukan secara ketat dan dianotasi dengan anotasi yang sesuai. Bersama-sama mereka membentuk lapisan akses data lengkap yang mengisolasi logika bisnis aplikasi dari detail implementasi SQLite.
Entity adalah kelas data yang mendeskripsikan struktur satu tabel dalam basis data. Setiap bidang kelas sesuai dengan kolom tabel, dan setiap baris dalam basis data sesuai dengan satu instance kelas. Anotasi @Entity memberi tahu Room bahwa kelas tersebut adalah tabel. Bidang dengan anotasi @PrimaryKey menentukan kunci utama, yang dapat berupa auto-increment atau gabungan. Untuk hubungan antar tabel digunakan @ForeignKey, yang memastikan integritas data di tingkat basis data.
@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) adalah antarmuka atau kelas abstrak yang mendeklarasikan operasi untuk bekerja dengan data: menyisipkan, membaca, memperbarui dan menghapus. Setiap operasi dianotasi dengan @Insert, @Query, @Update atau @Delete. Room secara otomatis menghasilkan implementasi antarmuka ini pada tahap kompilasi. Nilai khusus dimiliki oleh anotasi @Query, yang menerima kueri SQL sebagai string dan memeriksa kebenarannya pada tahap pembuatan.
@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 adalah kelas abstrak yang mewarisi RoomDatabase, berfungsi sebagai titik masuk ke basis data. Kelas ini berisi daftar semua Entity dan menyediakan metode abstrak untuk mendapatkan DAO. Kelas dianotasi dengan @Database, di mana versi skema dan daftar entitas ditentukan. Pembuatan instance basis data dilakukan melalui Room.databaseBuilder dengan menentukan konteks aplikasi, nama file, dan kelas Database.
Room tidak menggantikan SQLite, tetapi bekerja di atasnya sebagai lapisan abstraksi. Arsitektur internal mencakup pemroses anotasi, generator kode, dan kumpulan koneksi. Pada tahap kompilasi, pemroses anotasi menganalisis kelas Entity, DAO dan Database, kemudian menghasilkan kelas implementasi dengan akhiran _Impl. Semua kelas yang dihasilkan ditempatkan dalam paket pembuatan dan tidak terlihat langsung oleh pengembang.
Pembuatan kode pada tahap kompilasi — mekanisme sentral Room. Untuk setiap antarmuka DAO, dihasilkan kelas dengan implementasi lengkap semua metode yang dianotasi. Kueri SQL dari anotasi @Query diperiksa kebenarannya: pemroses mencocokkan nama kolom dengan bidang Entity dan memeriksa sintaks SQL. Saat mendeteksi kesalahan, kompilasi dihentikan dengan pesan yang jelas. Ini tidak mungkin dilakukan dengan penggunaan SQLiteOpenHelper mentah, di mana kesalahan hanya muncul saat runtime.
Proses pembuatan mencakup tiga tahap. Pertama — validasi skema: pemroses memeriksa apakah semua kelas yang disebutkan dalam @Database adalah Entity yang valid. Kedua — pembuatan badan DAO: untuk setiap metode dibuat implementasi menggunakan objek internal RoomSQLiteQuery yang menjalankan kueri siap pakai. Ketiga — pembuatan kelas Database_Impl, yang mengimplementasikan pembuatan dan pembukaan basis data serta inisialisasi semua objek DAO.
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)
}
}
}
Room tidak membuat kumpulan thread terpisah untuk operasi basis data. Secara default, kueri dijalankan di thread pemanggil dengan satu batasan: membaca dan menulis memblokir thread. Untuk kerja asinkron, Room terintegrasi dengan coroutine Kotlin melalui fungsi suspend, dengan LiveData melalui nilai kembalian dan dengan Flow melalui pembungkus reaktif. Ini memberi pengembang fleksibilitas dalam memilih solusi arsitektur untuk tugas tertentu.
Mari kita lihat contoh praktis pembuatan aplikasi untuk menyimpan catatan menggunakan Room. Aplikasi berisi satu tabel Note dengan bidang id, title, content dan timestamp. Pengguna dapat menambah, melihat, dan menghapus catatan. Untuk demonstrasi digunakan coroutine untuk operasi asinkron.
Untuk menghubungkan Room ke proyek Android, perlu menambahkan dependensi ke file build.gradle modul aplikasi. Room memerlukan tiga komponen: pustaka runtime, pemroses anotasi kapt, dan dukungan opsional untuk coroutine. Versi pustaka ditentukan dalam variabel room_version untuk kemudahan pembaruan. Mulai Room 2.4.0, KSP didukung sebagai alternatif kapt dengan kecepatan pembuatan yang lebih tinggi.
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"
// Opsional: pengujian
testImplementation "androidx.room:room-testing:$room_version"
}
Setelah mengonfigurasi dependensi, tiga file dibuat: Entity Note, antarmuka NoteDao dan kelas AppDatabase. Entity Note berisi bidang dengan anotasi @PrimaryKey dan @ColumnInfo. DAO menyediakan metode untuk menyisipkan, mendapatkan daftar, dan menghapus. Database menghubungkan Entity dan DAO melalui anotasi @Database.
@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)
}
File AppDatabase dideklarasikan sebagai kelas abstrak yang mewarisi RoomDatabase. Dalam anotasi @Database, semua Entity versi saat ini dan nomor versi skema disebutkan. Untuk mendapatkan instance, digunakan pola singleton melalui metode build Room.databaseBuilder dengan konteks aplikasi. Cache instance basis data mencegah pembuatan ganda yang dapat menyebabkan kebocoran memori.
Migrasi di Room adalah mekanisme untuk mengubah skema basis data saat memperbarui aplikasi tanpa kehilangan data yang ada. Ketika pengguna menginstal versi baru dengan Entity yang dimodifikasi, Room mendeteksi ketidakcocokan versi dan menjalankan langkah migrasi yang ditentukan. Tanpa migrasi, basis data akan dihapus dan dibuat ulang, yang menyebabkan hilangnya semua data pengguna yang tersimpan.
Migrasi dijelaskan oleh kelas Migration, yang menerima versi awal dan akhir basis data. Di dalam metode migrate, kueri SQL ALTER TABLE atau CREATE TABLE dijalankan untuk mengubah skema. Room tidak dapat secara otomatis menentukan perubahan skema — pengembang harus menulis migrasi secara manual untuk setiap perubahan Entity. Mulai versi Room 2.4.0, fungsi eksperimental autoMigrations tersedia untuk pembuatan migrasi otomatis.
Fungsi autoMigrations memungkinkan Room untuk secara otomatis menghasilkan migrasi berdasarkan perbedaan antara versi Entity. Untuk menggunakannya, cukup tambahkan anotasi @AutoMigration di @Database dan tentukan ekspor skema ke JSON. Room membandingkan skema versi yang berdekatan dan menghasilkan kueri ALTER yang diperlukan. Namun autoMigrations hanya mendukung perubahan yang kompatibel mundur: penambahan kolom, pembuatan indeks, dan perubahan tipe dengan konversi yang kompatibel.
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()
Saat menambahkan perubahan kompleks, seperti mengganti nama kolom atau menggabungkan tabel, diperlukan migrasi manual menggunakan tabel sementara. Skenario tipikal: buat tabel sementara dengan skema lama, salin data dari tabel lama ke tabel baru dengan konversi, hapus tabel lama dan ganti nama tabel sementara. Room menjamin bahwa semua migrasi dijalankan dalam satu transaksi, dan jika terjadi kesalahan, perubahan akan dibatalkan sepenuhnya.
Pertanyaan yang Sering Diajukan
Room menyediakan abstraksi ORM dengan anotasi dan validasi SQL pada tahap kompilasi, sementara SQLiteOpenHelper memerlukan penulisan manual semua kueri dan manajemen koneksi. Room secara otomatis menghasilkan kode untuk operasi CRUD dan terintegrasi dengan komponen arsitektur Android, termasuk LiveData dan Flow.
Room mendukung semua tipe primitif Java: Int, Long, Boolean, Float, Double, serta String, ByteArray dan Date. Untuk tipe kompleks seperti List atau Enum, digunakan TypeConverters — metode konversi statis yang mengubah tipe non-standar menjadi format yang didukung SQLite.
Ya, Room mendukung panggilan sinkron tanpa coroutine, tetapi mereka memblokir thread tempat mereka dijalankan. Untuk kerja asinkron, dapat digunakan LiveData atau RxJava sebagai pengganti coroutine. Google merekomendasikan penggunaan coroutine sebagai cara utama akses data asinkron di proyek baru.
Jika Room mendeteksi ketidakcocokan versi basis data dan tidak menemukan migrasi yang sesuai, secara default akan muncul IllegalStateException dengan deskripsi kesalahan. Pengembang dapat menimpa perilaku ini dengan metode fallbackToDestructiveMigration, yang akan menghapus basis data yang ada dan membuat yang baru dengan kehilangan semua data.
Room mendukung relasi melalui objek bersarang dengan anotasi @Embedded dan melalui kelas relasi dengan anotasi @Relation. Untuk kueri kompleks dengan penggabungan tabel, digunakan kelas POJO kustom yang bidangnya diisi dari hasil @Query dengan operator JOIN di SQL.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga