Room, Android'de yerel veritabanlarıyla çalışmak için SQLite üzerinde bir soyutlama katmanı sağlayan Android Jetpack'in bir ORM kütüphanesidir. Android Developers, 2025 resmi dokümantasyonuna göre, Room, derleme zamanında açıklamalara dayalı olarak otomatik olarak DAO uygulamaları oluşturur ve doğrudan SQLiteOpenHelper kullanımına kıyasla yaklaşık %70 oranında kalıp kodu ortadan kaldırır. Kütüphane, derleme aşamasında SQL sorgu doğrulaması gerçekleştirir ve uygulama bir cihazda çalıştırılmadan önce sözdizimi hatalarının tespit edilmesini sağlar.
Önemli Noktalar
Room, Android platformunda yerel SQLite veritabanlarıyla çalışmayı basitleştirmek için Google tarafından oluşturulan Android Jetpack'in bir ORM kütüphanesidir. Veri şemasını tanımlamak için açıklamalar sağlar ve derleme zamanında otomatik olarak DAO arayüz uygulamaları oluşturur. Doğrudan SQLiteOpenHelper kullanımının aksine, Room geliştiriciyi veritabanı bağlantıları oluşturma, açma ve yönetme için önemli miktarda kalıp kodu yazmaktan kurtarır.
Kütüphane, Google I/O 2017'de Android mimari bileşenlerinin bir parçası olarak tanıtıldı. O zamandan beri Room, yerel veri depolama için fiili standart haline geldi ve Android için GreenDAO ve Realm gibi çözümleri popülerlikte geride bıraktı. Google'a göre, kütüphane Google Play'de yayınlanan ve cihazda yerel verilerle çalışan uygulamaların %60'ından fazlasında kullanılmaktadır.
Temel özellik, bir açıklama işlemcisi kullanarak derleme zamanında SQL sorgu doğrulamasıdır. Bir geliştirici SQL komutunda hata yaparsa, örneğin var olmayan bir sütun adı belirtirse, uygulama yüklenmeden önce derleme bir hatayla başarısız olur. Bu, bu tür hataların yalnızca çalışma zamanında, genellikle üretim ortamında tespit edildiği SQLiteOpenHelper yaklaşımından temel olarak farklıdır.
SQLite yalnızca beş veri türünü destekler: TEXT, INTEGER, REAL, BLOB ve NULL. Ancak Java ve Kotlin'de karmaşık türler kullanılır: Date, List, Enum ve özel nesneler. Bunları depolamak için Room, TypeConverters mekanizmasını sağlar — karmaşık bir türü SQLite'ın anlayabileceği ilkel bir türe dönüştüren statik yöntemler. Örneğin, bir Date nesnesi Long'a (zaman damgası) ve List<String>, Gson veya Moshi aracılığıyla bir JSON dizesine dönüştürülür.
@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()
Bir dönüştürücü bildirmek için, statik bir yönteme @TypeConverter açıklamasını eklemek ve veritabanı düzeyinde @TypeConverters açıklamasında dönüştürücü sınıfını belirtmek yeterlidir. Room, dönüştürme yöntemlerini manuel olarak çağırmaya gerek kalmadan her SQL sorgusunda ilgili türü okurken ve yazarken otomatik olarak dönüştürücüyü uygular.
Room üç ana bileşenden oluşur: Entity, DAO ve Database. Her biri kesin olarak tanımlanmış bir rol oynar ve ilgili açıklama ile açıklanır. Birlikte, uygulamanın iş mantığını SQLite uygulama ayrıntılarından ayıran eksiksiz bir veri erişim katmanı oluştururlar.
Entity, veritabanındaki bir tablonun yapısını tanımlayan bir veri sınıfıdır. Sınıfın her alanı bir tablo sütununa karşılık gelir ve veritabanındaki her satır sınıfın bir örneğine karşılık gelir. @Entity açıklaması, Room'a sınıfın bir tablo olduğunu bildirir. @PrimaryKey açıklamasına sahip alan, otomatik artan veya bileşik olabilen birincil anahtarı tanımlar. @ForeignKey, veritabanı düzeyinde veri bütünlüğünü sağlayarak tablolar arasındaki ilişkiler için kullanılır.
@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), verilerle çalışmak için işlemler bildiren bir arayüz veya soyut sınıftır: ekleme, okuma, güncelleme ve silme. Her işlem @Insert, @Query, @Update veya @Delete ile açıklanır. Room, bu arayüzün uygulamasını derleme zamanında otomatik olarak oluşturur. @Query açıklaması özellikle değerlidir — bir SQL sorgusunu dize olarak kabul eder ve derleme zamanında doğruluğunu doğrular.
@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, RoomDatabase'i genişleten ve veritabanına giriş noktası görevi gören soyut bir sınıftır. Tüm Entity'lerin bir listesini içerir ve DAO'ları almak için soyut yöntemler sağlar. Sınıf, şema sürümünü ve varlık listesini belirten @Database ile açıklanır. Veritabanı örneği, uygulama bağlamı, dosya adı ve Database sınıfı ile Room.databaseBuilder aracılığıyla oluşturulur.
Room SQLite'ın yerini almaz, onun üzerinde bir soyutlama katmanı olarak çalışır. İç mimari, bir açıklama işlemcisi, kod oluşturucu ve bağlantı havuzu içerir. Derleme zamanında, açıklama işlemcisi Entity, DAO ve Database sınıflarını analiz eder ve ardından _Impl sonekine sahip uygulama sınıfları oluşturur. Oluşturulan tüm sınıflar derleme paketine yerleştirilir ve geliştirici tarafından doğrudan görünmez.
Derleme zamanında kod oluşturma, Room'un merkezi mekanizmasıdır. Her DAO arayüzü için, açıklanmış tüm yöntemlerin tam uygulamasına sahip bir sınıf oluşturulur. @Query açıklamasından gelen SQL sorguları doğruluk açısından doğrulanır: işlemci sütun adlarını Entity alanlarıyla eşleştirir ve SQL sözdizimini kontrol eder. Bir hata bulunursa, derleme net bir mesajla kesintiye uğrar. Bu, hataların yalnızca çalışma zamanında ortaya çıktığı ham SQLiteOpenHelper kullanılırken mümkün değildir.
Oluşturma süreci üç aşamadan oluşur. Birinci — şema doğrulaması: işlemci, @Database'de listelenen tüm sınıfların geçerli Entity'ler olup olmadığını kontrol eder. İkinci — DAO gövdesi oluşturma: her yöntem için, hazırlanmış sorguları yürüten dahili RoomSQLiteQuery nesnesi kullanılarak bir uygulama oluşturulur. Üçüncü — Database_Impl sınıfının oluşturulması: veritabanı oluşturma ve açmanın yanı sıra tüm DAO nesnelerinin başlatılmasını yönetir.
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, veritabanı işlemleri için ayrı bir iş parçacığı havuzu oluşturmaz. Varsayılan olarak, sorgular çağıran iş parçacığında bir sınırlama ile yürütülür: okuma ve yazma iş parçacığını bloke eder. Zaman uyumsuz çalışma için Room, askıya alma işlevleri aracılığıyla Kotlin eş yordamlarıyla, dönüş değerleri aracılığıyla LiveData ile ve reaktif sarmalayıcılar aracılığıyla Flow ile entegre olur. Bu, geliştiriciye belirli bir görev için mimari çözümü seçme esnekliği sağlar.
Room kullanarak not alma uygulaması oluşturmanın pratik bir örneğine bakalım. Uygulama, id, title, content ve timestamp alanlarına sahip bir Note tablosu içerir. Kullanıcılar not ekleyebilir, görüntüleyebilir ve silebilir. Zaman uyumsuz işlemler için eş yordamlar kullanılır.
Room'u bir Android projesine entegre etmek için, modül düzeyindeki build.gradle dosyasına bağımlılıklar ekleyin. Room üç bileşen gerektirir: çalışma zamanı kütüphanesi, kapt açıklama işlemcisi ve isteğe bağlı eş yordam desteği. Kütüphane sürümü, kolay güncelleme için room_version değişkeninde belirtilir. Room 2.4.0'dan itibaren, daha hızlı derleme hızlarıyla kapt'a alternatif olarak KSP desteklenmektedir.
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"
// İsteğe bağlı: test
testImplementation "androidx.room:room-testing:$room_version"
}
Bağımlılıkları ayarladıktan sonra üç dosya oluşturun: Note Entity, NoteDao arayüzü ve AppDatabase sınıfı. Note Entity, @PrimaryKey ve @ColumnInfo açıklamalarına sahip alanlar içerir. DAO, ekleme, listeyi alma ve silme için yöntemler sağlar. Database, @Database açıklaması aracılığıyla Entity ve DAO'yu birbirine bağlar.
@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)
}
AppDatabase dosyası, RoomDatabase'i genişleten soyut bir sınıf olarak bildirilir. @Database açıklaması, geçerli sürüm için tüm Entity'leri ve şema sürüm numarasını belirtir. Bir örnek almak için, uygulama bağlamı ile Room.databaseBuilder'ın build yöntemi aracılığıyla tekil desen kullanılır. Veritabanı örneğini önbelleğe almak, bellek sızıntılarına neden olabilecek birden çok oluşturmayı önler.
Geçişler, Room'da mevcut verileri kaybetmeden bir uygulamayı güncellerken veritabanı şemasını değiştirmek için bir mekanizmadır. Bir kullanıcı değiştirilmiş Entity'ler içeren yeni bir sürüm yüklediğinde, Room sürüm uyuşmazlığını algılar ve belirtilen geçiş adımlarını yürütür. Geçiş olmadan, veritabanı silinir ve yeniden oluşturulur, bu da kullanıcı tarafından kaydedilen tüm verilerin kaybına yol açar.
Bir geçiş, veritabanının başlangıç ve bitiş sürümlerini alan Migration sınıfı tarafından tanımlanır. migrate yönteminin içinde, şemayı değiştirmek için bir ALTER TABLE veya CREATE TABLE SQL sorgusu yürütülür. Room şema değişikliklerini otomatik olarak algılayamaz — geliştirici her Entity değişikliği için manuel olarak bir geçiş yazmalıdır. Room 2.4.0'dan itibaren, otomatik geçiş oluşturma için deneysel autoMigrations özelliği mevcuttur.
autoMigrations özelliği, Room'un Entity sürümleri arasındaki farklılıklara dayalı olarak otomatik olarak geçişler oluşturmasını sağlar. Kullanmak için, @Database'e @AutoMigration açıklamasını eklemek ve JSON'a şema dışa aktarmayı etkinleştirmek yeterlidir. Room bitişik sürümlerin şemalarını karşılaştırır ve gerekli ALTER sorgularını oluşturur. Ancak autoMigrations yalnızca geriye dönük uyumlu değişiklikleri destekler: sütun ekleme, dizin oluşturma ve uyumlu dönüşümlerle türleri değiştirme.
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()
Sütunları yeniden adlandırma veya tabloları birleştirme gibi karmaşık değişiklikler için, ara tablolar kullanılarak manuel geçiş gereklidir. Tipik bir senaryo: eski şemayla geçici bir tablo oluşturun, dönüşümlerle eski tablodan yenisine veri kopyalayın, eski tabloyu silin ve geçici olanı yeniden adlandırın. Room, tüm geçişlerin tek bir işlemde yürütülmesini garanti eder ve bir hata oluşursa değişiklikler tamamen geri alınır.
Sıkça Sorulan Sorular
Room, açıklamalar ve derleme zamanında SQL doğrulaması ile ORM soyutlaması sağlarken, SQLiteOpenHelper tüm sorguların manuel olarak yazılmasını ve bağlantıların yönetilmesini gerektirir. Room, CRUD işlemleri için otomatik olarak kod oluşturur ve LiveData ve Flow dahil olmak üzere Android mimari bileşenleriyle entegre olur.
Room tüm Java ilkel türlerini destekler: Int, Long, Boolean, Float, Double'nin yanı sıra String, ByteArray ve Date. List veya Enum gibi karmaşık türler için, TypeConverters kullanılır — standart olmayan türleri SQLite uyumlu biçimlere dönüştüren statik dönüştürme yöntemleri.
Evet, Room eş yordamlar olmadan senkron çağrıları destekler, ancak çalıştıkları iş parçacığını bloke ederler. Zaman uyumsuz çalışma için eş yordamlar yerine LiveData veya RxJava kullanabilirsiniz. Google, yeni projelerde zaman uyumsuz veri erişimi için birincil yöntem olarak eş yordamların kullanılmasını önerir.
Room bir veritabanı sürüm uyuşmazlığı tespit eder ve uygun bir geçiş bulamazsa, varsayılan olarak bir hata açıklamasıyla IllegalStateException fırlatır. Geliştirici, bu davranışı fallbackToDestructiveMigration yöntemiyle geçersiz kılabilir; bu yöntem mevcut veritabanını siler ve tüm verileri kaybederek yeni bir tane oluşturur.
Room, @Embedded açıklamasıyla iç içe nesneler ve @Relation açıklamasıyla ilişki sınıfları aracılığıyla ilişkileri destekler. Tablo birleştirmeleri içeren karmaşık sorgular için, alanları SQL JOIN deyimleriyle @Query sonuçlarından doldurulan özel POJO sınıfları kullanılır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun