Room: Schlüsselkonzepte, Entity, DAO und die Arbeit mit Datenbanken

Autor: IT Sectr Veröffentlicht: 2026-05-04 Lesezeit: 8 Min.

Room ist eine Bibliothek für die Arbeit mit SQLite in Android, Teil von Jetpack. Sie bietet eine Abstraktionsschicht über rohes SQLite und automatisiert die Tabellenerstellung, Abfrageausführung und Datenkonvertierung in Kotlin- und Java-Objekte. Laut Android Developers kompiliert Room SQL-Abfragen zur Build-Zeit und überprüft die Syntaxkorrektheit sowie die Beziehungen zwischen Entity und Tabellen.

Wichtige Punkte

  • Room ist eine Jetpack-ORM-Bibliothek für die Arbeit mit SQLite in Android-Apps.
  • Entity ist eine mit @Entity annotierte Klasse, jede Instanz entspricht einer Zeile in einer Tabelle.
  • DAO ist ein Datenzugriffsobjekt mit annotierten Methoden für SQL-Abfragen.
  • Database ist eine abstrakte Klasse, die RoomDatabase erweitert und Entity mit DAO verbindet.
  • Migration ist ein Mechanismus zum sicheren Ändern des Datenbankschemas ohne Datenverlust.

Was ist Room und warum braucht man es

Room ist eine Persistenzbibliothek von Android Jetpack, die objektrelationales Mapping für SQLite bereitstellt. Room löst drei Hauptprobleme von rohem SQLite: das Schreiben großer Mengen an Boilerplate-Code zur Tabellenerstellung, das Fehlen der SQL-Abfrageüberprüfung zur Kompilierzeit und die manuelle Konvertierung von Cursor in Objekte.

Die Bibliothek verwendet einen Annotationsprozessor (kapt oder KSP), der die Implementierung der abstrakten RoomDatabase- und DAO-Klassen zur Build-Zeit generiert. Dadurch wird sichergestellt, dass Syntaxfehler in SQL und Typkonflikte bereits vor dem Ausführen der Anwendung erkannt werden, nicht erst zur Laufzeit nach der Veröffentlichung im Google Play Store.

Laut Google I/O 2023 wird Room in 68% der Android-Anwendungen verwendet, die mit lokalen Daten arbeiten. Es ist der Standard für die Datenspeicherung auf dem Gerät, empfohlen von Google für alle neuen Projekte — anstelle der veralteten SQLiteOpenHelper und ContentProvider.

Integrieren Sie Room in Projekte, die lokales Caching von Serverdaten, Offline-Modus oder die Speicherung strukturierter Benutzerdaten mit der Möglichkeit komplexer SQL-Abfragen erfordern.

Room ist Teil von Android Jetpack und wird von Google offiziell für alle neuen Projekte empfohlen, die mit lokalen Daten arbeiten. Im Gegensatz zu Realm oder ObjectBox verwendet Room natives SQLite, was die Kompatibilität mit allen Datenbanktools von Drittanbietern gewährleistet — von DB Browser bis DataGrip. Entwickler können die .db-Datei der Anwendung öffnen und SQL-Abfragen direkt ausführen, was das Debugging und die Datenanalyse während der Entwicklung vereinfacht.

Entity und Annotationen in Room

Entity ist eine mit @Entity annotierte Datenklasse, die Room in eine Datenbanktabelle umwandelt. Jedes Feld der Klasse wird zu einer Tabellenspalte, jede Instanz zu einer Zeile. Room verwendet Reflektion für den Feldzugriff, daher ist die @PrimaryKey-Annotation für eine obligatorische ID erforderlich.

Wichtige Annotationen

Die @Entity-Annotation teilt Room mit, dass die Klasse eine Tabelle ist. Der Parameter tableName legt den Tabellennamen fest, wenn er vom Klassennamen abweicht. @PrimaryKey definiert den Primärschlüssel mit Auto-Generierung durch autoGenerate = true.

kotlin
@Entity(tableName = "users")
data class User(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    @ColumnInfo(name = "full_name")
    val name: String,
    @Ignore
    val tempData: String?
)

@ColumnInfo gibt den Spaltennamen in der Tabelle an, wenn er vom Kotlin-Feldnamen abweicht. @Ignore schließt ein Feld aus der Tabelle aus — es wird nicht in der Datenbank gespeichert. @ForeignKey beschreibt Fremdschlüssel für Beziehungen zwischen Tabellen mit Kaskadenoperationen beim Löschen oder Aktualisieren.

Room unterstützt verschachtelte Objekte durch die @Embedded-Annotation. Die Felder der verschachtelten Klasse werden mit einem Präfix in Spalten der Elterntabelle erweitert, um Namenskonflikte zu vermeiden. Beispielsweise erzeugt eine Address-Klasse mit city- und street-Feldern, die in User eingebettet ist, die Spalten address_city und address_street in der Tabelle users, wodurch separate Tabellen für einfache Wertobjekte überflüssig werden.

Typkonverter

Room unterstützt nur primitive Typen und deren Wrapper. Zum Speichern von Listen, Date oder benutzerdefinierten Typen verwenden Sie @TypeConverter — statische Methoden zur Konvertierung zwischen einem benutzerdefinierten Typ und einem SQLite-Primitiv, z.B. zwischen List und einem JSON-String.

DAO und SQL-Abfragen

DAO (Data Access Object) ist ein mit @Dao annotiertes Interface oder eine abstrakte Klasse mit Methoden für den Datenzugriff. Jede Methode wird mit einer SQL-Operation annotiert: @Insert, @Update, @Delete oder @Query mit einer expliziten SQL-Abfrage.

@Query mit Kompilierzeit-Prüfung

Die @Query-Annotation nimmt einen SQL-String entgegen, den Room zur Kompilierzeit auf Syntaxkorrektheit und Übereinstimmung der Spaltennamen mit Entity-Feldern prüft. Room unterstützt parametrisierte Abfragen durch die Syntax :paramName.

kotlin
@Dao
interface UserDao {
    @Query("SELECT * FROM users WHERE id = :userId")
    suspend fun getUserById(userId: Int): User?

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUser(user: User)

    @Query("SELECT * FROM users ORDER BY name ASC")
    fun getAllUsers(): Flow<List<User>>
}

@Insert unterstützt OnConflictStrategy-Optionen zur Behandlung von Konflikten beim Einfügen doppelter Datensätze. Flow als Rückgabetyp sorgt für reaktive UI-Updates bei jeder Datenänderung in der Tabelle — das Abonnement wird bei jedem INSERT, UPDATE oder DELETE automatisch neu gestartet.

@Transaction für komplexe Operationen

Die @Transaction-Annotation garantiert die atomare Ausführung mehrerer Operationen in einem einzigen Transaktionsblock. Room sperrt die Datenbank während der Ausführung und verhindert so Wettlaufsituationen bei gleichzeitigem Zugriff aus mehreren Threads.

Database und Schema-Migrationen

RoomDatabase ist eine abstrakte Klasse, die Entity und DAO zu einem einzigen Datenbankzugriffspunkt zusammenfasst. Sie wird über Room.databaseBuilder mit der Schema-Version und einer Liste von Entity-Klassen erstellt. Die Datenbankinstanz sollte als Singleton über einen lazy-Delegaten erstellt werden, um mehrere Verbindungen zu vermeiden.

Migrationen

Eine Migration in Room ist eine Migration-Klasse, die ein SQL-Skript für den Übergang von einer alten Schema-Version zu einer neuen beschreibt. Wenn bei einer Schemaänderung keine Migration bereitgestellt wird, wirft Room eine IllegalStateException. Dies schützt vor versehentlichem Benutzerdatenverlust beim Aktualisieren der Anwendung.

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

val db = Room.databaseBuilder(
    getApplication(),
    AppDatabase::class.java,
    "app_database"
).addMigrations(migration_1_2)
 .build()

Für die Entwicklung können Sie fallbackToDestructiveMigration verwenden, das bei Versionskonflikten die alte Datenbank löscht und eine neue erstellt. Dieser Modus ist nur für das Debugging gedacht — Produktionsversionen müssen ordnungsgemäße Migrationen enthalten.

Zum Testen der Datenbank bietet Room die spezielle Klasse Room.inMemoryTestBuilder, die eine Datenbank im Arbeitsspeicher erstellt, ohne sie auf die Festplatte zu schreiben. Nach jedem Test wird die Datenbank automatisch zerstört, was eine vollständige Isolation der Testszenarien gewährleistet. In Kombination mit der Bibliothek android-arch-core-testing können Entwickler den Datenbanklebenszyklus verwalten und die Korrektheit von Migrationen überprüfen, ohne den Zustand manuell bereinigen zu müssen.

Die Leistung von Room hängt direkt von der Abfragestruktur und den Indizes ab. Zur Analyse langsamer Abfragen stellt Room das enableQueryCallback-Flag bereit, das alle SQL-Abfragen mit Ausführungszeit protokolliert. Entwickler können dieses Protokoll verwenden, um Abfragen zu finden, die länger als 100 Millisekunden dauern, und sie durch Hinzufügen zusammengesetzter Indizes über die @Index-Annotation in @Entity oder durch Umschreiben von Unterabfragen als direkte JOIN-Operationen mit @Relation optimieren.

Room unterstützt auch die Datenbankverschlüsselung über SQLCipher. Das Hinzufügen der Bibliothek net.zetetic:android-database-sqlcipher und die Verwendung von SupportFactory anstelle der Standardimplementierung bietet eine transparente Verschlüsselung aller Daten auf der Festplatte, ohne DAO-Abfragen oder die Entity-Struktur zu ändern. Dies ist für Anwendungen erforderlich, die mit persönlichen Benutzerdaten umgehen, und entspricht der DSGVO sowie dem russischen Bundesgesetz 152-FZ zum Schutz personenbezogener Daten. Das Verschlüsselungspasswort kann im Android Keystore gespeichert werden, um es vor dem Auslesen durch Tools auf gerooteten Geräten zu schützen.

Room mit Kotlin Coroutines und Flow

Room unterstützt Kotlin Coroutines nativ ab Version 2.1. DAO-Methoden können als suspend-Funktionen deklariert werden, die Abfragen im Hintergrundthread ausführen, ohne den Hauptthread zu blockieren. Room verwaltet die Dispatcher automatisch und verwendet Dispatchers.IO für Lese- und Schreibabfragen.

Für reaktive Abfragen gibt Room einen Flow zurück — einen kalten Datenstrom, der bei jeder Änderung der betroffenen Tabelle einen neuen Wert ausgibt. Das ViewModel abonniert den Flow über stateIn oder collect und sorgt so für automatische UI-Updates ohne manuelle Benachrichtigung des Adapters.

Room unterstützt auch Paging 3 über eine spezielle PagingSource-Implementierung, die Daten seitenweise aus SQLite lädt. Dies ist effizient für große Listen mit Tausenden von Datensätzen: Paging 3 lädt nur die auf dem Bildschirm sichtbaren Zeilen und aktualisiert sie bei Datenbankänderungen automatisch.

Verwenden Sie Paging 3 mit Room zum Anzeigen von Nachrichtenfeeds, Operationslogs oder Produktlisten mit Offline-Zugriff und unendlichem Scrollen.

Häufig gestellte Fragen

Wie unterscheidet sich Room von SQLiteOpenHelper?

Room automatisiert die Tabellenerstellung, die Cursor-zu-Objekt-Konvertierung und die SQL-Überprüfung zur Kompilierzeit. SQLiteOpenHelper erfordert das manuelle Schreiben des Schemas, die Verarbeitung von Cursor und hat keine Abfrageüberprüfung vor dem Ausführen der Anwendung, was das Fehlerrisiko erhöht.

Muss ich für jede Schemaänderung Migrationen schreiben?

Ja, beim Ändern einer Entity (Hinzufügen/Entfernen eines Feldes, Ändern eines Typs) ist eine Migration erforderlich. Ohne sie wirft Room beim Start eine IllegalStateException. Für die Entwicklung können Sie fallbackToDestructiveMigration aktivieren, aber Produktionsversionen benötigen korrekte Migrationsskripte.

Unterstützt Room Beziehungen zwischen Tabellen?

Room unterstützt @ForeignKey für Kaskadenoperationen und @Relation für verschachtelte Objekte. Für komplexe JOIN-Abfragen verwenden Sie die @Transaction-Annotation mit @Query, die ein POJO mit verschachtelten Entitäten über @Embedded und @Relation zurückgibt.

Kann ich Room mit Java ohne Kotlin verwenden?

Ja, Room ist vollständig kompatibel mit Java. Statt suspend-Funktionen verwenden Sie LiveData oder RxJava Observable; statt Flow verwenden Sie LiveData. Room mit Java unterstützt alle gleichen Annotationen, erfordert jedoch mehr Boilerplate-Code für asynchrone Operationen.

Wie funktioniert die Room-Datenbankverschlüsselung?

Room unterstützt Verschlüsselung über SQLCipher von Zetetic. Statt Room.databaseBuilder verwenden Sie SupportFactory aus der Bibliothek net.zetetic:android-database-sqlcipher und übergeben das Verschlüsselungspasswort. Alle Daten auf der Festplatte werden für DAO-Abfragen transparent verschlüsselt.

Zusammenfassung

  • Room ist eine Jetpack-ORM-Bibliothek für SQLite mit Kompilierzeit-SQL-Prüfung.
  • @Entity beschreibt die Tabelle, @PrimaryKey ist der Identifikator, @ColumnInfo der Spaltenname.
  • @Dao enthält Methoden mit @Query, @Insert, @Update und @Delete für den Datenzugriff.
  • RoomDatabase kombiniert Entity und DAO, erstellt über Room.databaseBuilder.
  • Migrationen (Migration) beschreiben SQL-Skripte für Schemaänderungen ohne Datenverlust.
  • Room unterstützt nativ Kotlin Coroutines (suspend) und Flow für reaktive UI-Updates.
  • Für große Listen verwenden Sie Paging 3 mit Room über PagingSource für seitenweises Laden.

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch