Room-Datenbank in Kotlin – Entity, DAO und Database in unter 30 Zeilen
Daten lokal auf dem Gerät speichern, ohne selbst SQL-Strings zusammenzubauen: Room ist die empfohlene Persistenz-Bibliothek für Android. Die drei Bausteine – Entity, DAO und Database – und wie sie zusammenspielen.
Sobald deine App Daten behalten soll, die einen Neustart überleben – Notizen, ein Warenkorb, ein Cache – brauchst du eine lokale Datenbank. Auf Android ist Room dafür der empfohlene Weg: eine Abstraktionsschicht über SQLite, die dir das Zusammenbauen von SQL-Strings abnimmt und Fehler schon zur Compile-Zeit findet. Room besteht aus genau drei Bausteinen.
1. Entity – die Tabelle
Eine data class mit @Entity beschreibt eine Tabelle, jedes Feld ist eine Spalte:
@Entity(tableName = "notes")
data class Note(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val title: String,
val createdAt: Long,
)2. DAO – die Zugriffe
Das Data Access Object ist ein Interface mit deinen Abfragen. Room generiert die Implementierung:
@Dao
interface NoteDao {
@Query("SELECT * FROM notes ORDER BY createdAt DESC")
fun observeAll(): Flow<List<Note>> // liefert bei jeder Änderung neu
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun upsert(note: Note)
@Delete
suspend fun delete(note: Note)
}3. Database – die Klammer
Eine abstrakte Klasse verbindet Entities und DAOs:
@Database(entities = [Note::class], version = 1)
abstract class AppDb : RoomDatabase() {
abstract fun noteDao(): NoteDao
}
// Einmal bauen (am besten über Dependency Injection als Singleton):
val db = Room.databaseBuilder(context, AppDb::class.java, "app.db").build()
val dao = db.noteDao()Warum das im Alltag angenehm ist
- Main-sicher von Haus aus.
suspend-Funktionen undFlow-Abfragen wechseln intern selbst den Thread – du musst Datenbankzugriffe nicht mehr von Hand inwithContext(Dispatchers.IO)wickeln. - Reaktiv mit Flow. Gibt ein DAO einen
Flowzurück, bekommt dein UI bei jeder Änderung automatisch die neue Liste. In Compose liest du das mitcollectAsStateWithLifecycle(). - Fehler früh. Room prüft deine
@Query-Strings beim Kompilieren gegen das Schema – ein Tippfehler im SQL fällt sofort auf, nicht erst beim Nutzer. - Migrationen nicht vergessen. Änderst du das Schema, musst du
versionerhöhen und eine Migration angeben (oder in der EntwicklungfallbackToDestructiveMigration()nutzen – aber niemals in Produktion, das löscht die Daten).
Wenn du eine Android-App brauchst, die Daten sauber und offline-fähig speichert, sprich mich an.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Room-Migrationen – das Schema ändern, ohne Nutzerdaten zu verlieren
Eine neue Spalte in der Entity, und beim nächsten Start ist der Spielstand weg – weil fallbackToDestructiveMigration die Datenbank einfach löscht. So machst du es richtig, inklusive Test.
stateIn und shareIn – aus einem kalten Flow wird geteilter Zustand
Jeder Sammler eines kalten Flows startet die Arbeit neu – zwei Beobachter, zwei Datenbankabfragen. stateIn und shareIn machen daraus einen Strom, den sich alle teilen, samt aktuellem Wert und Abschalten bei Inaktivität.
viewModelScope – Coroutinen, die mit dem Bildschirm verschwinden
Eine Coroutine, die nach dem Schließen des Bildschirms weiterläuft, schreibt in ein ViewModel, das niemand mehr sieht – und hält im schlimmsten Fall die ganze Activity im Speicher. viewModelScope beendet sie automatisch.